Exemple #1
0
int format_ebml_get_plugin(source_t *source)
{

    ebml_source_state_t *ebml_source_state = calloc(1, sizeof(ebml_source_state_t));
    format_plugin_t *plugin = calloc(1, sizeof(format_plugin_t));

    plugin->get_buffer = ebml_get_buffer;
    plugin->write_buf_to_client = ebml_write_buf_to_client;
    plugin->create_client_data = ebml_create_client_data;
    plugin->free_plugin = ebml_free_plugin;
    plugin->write_buf_to_file = ebml_write_buf_to_file;
    plugin->set_tag = NULL;
    plugin->apply_settings = NULL;

    plugin->contenttype = httpp_getvar(source->parser, "content-type");

    plugin->_state = ebml_source_state;
    vorbis_comment_init(&plugin->vc);
    source->format = plugin;

    ebml_source_state->ebml = ebml_create();
    return 0;
}
static void
gst_vorbis_enc_set_metadata (GstVorbisEnc * enc)
{
  GstTagList *merged_tags;
  const GstTagList *user_tags;

  vorbis_comment_init (&enc->vc);

  user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc));

  GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags);
  GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags);

  /* gst_tag_list_merge() will handle NULL for either or both lists fine */
  merged_tags = gst_tag_list_merge (user_tags, enc->tags,
      gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));

  if (merged_tags) {
    GST_DEBUG_OBJECT (enc, "merged   tags = %" GST_PTR_FORMAT, merged_tags);
    gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc);
    gst_tag_list_free (merged_tags);
  }
}
encoder_instance encoder_create_vbr(int ch, int bitrate, float quality) {
  encoder_instance state = malloc(sizeof(struct encoder_state));
  state->data = NULL;
  state->data_len = 0;
  
  vorbis_info_init(&state->vi);
  
  if (vorbis_encode_init_vbr(&state->vi, ch, bitrate, quality) != 0) {
    free(state);
    return NULL;
  }
  
  vorbis_comment_init(&state->vc);
  vorbis_comment_add_tag(&state->vc, "ENCODER", "libvorbis.js");
  
  vorbis_analysis_init(&state->vd, &state->vi);
  vorbis_block_init(&state->vd, &state->vb);
  
  srand(time(NULL));
  ogg_stream_init(&state->os, rand());
  
  return state;
}
Exemple #4
0
/*****************************************************************************
 * OpenDecoder: probe the decoder and return score
 *****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t*)p_this;
    decoder_sys_t *p_sys;

    if( p_dec->fmt_in.i_codec != VLC_CODEC_VORBIS )
        return VLC_EGENERIC;

    /* Allocate the memory needed to store the decoder's structure */
    p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) );
    if( unlikely( !p_sys ) )
        return VLC_ENOMEM;

    /* Misc init */
    date_Set( &p_sys->end_date, 0 );
    p_sys->i_last_block_size = 0;
    p_sys->b_packetizer = false;
    p_sys->b_has_headers = false;

    /* Take care of vorbis init */
    vorbis_info_init( &p_sys->vi );
    vorbis_comment_init( &p_sys->vc );

    /* Set output properties */
    p_dec->fmt_out.i_cat = AUDIO_ES;
#ifdef MODULE_NAME_IS_tremor
    p_dec->fmt_out.i_codec = VLC_CODEC_S32N;
#else
    p_dec->fmt_out.i_codec = VLC_CODEC_FL32;
#endif

    /* Set callbacks */
    p_dec->pf_decode_audio = DecodeBlock;
    p_dec->pf_packetize    = DecodeBlock;

    return VLC_SUCCESS;
}
Exemple #5
0
BOOL OggDec::GetWaveformat(WAVEFORMATEX *wfx,char *buf)
{
	char	*buffer;

	if(NULL==wfx)return FALSE;
	if(bWaveGet){
		memcpy(wfx,&wfmt,sizeof(WAVEFORMATEX));
		return TRUE;
	}else if(NULL==buf){
		return FALSE;
	}
	buffer=ogg_sync_buffer(&oy,4096);
	memcpy(buffer,buf,4096);
	ogg_sync_wrote(&oy,4096);
	ogg_sync_pageout(&oy,&og);
	ogg_stream_init(&os,ogg_page_serialno(&og));
	vorbis_info_init(&vi);
	vorbis_comment_init(&vc);
	ogg_stream_pagein(&os,&og);
	ogg_stream_packetout(&os,&op);
	vorbis_synthesis_headerin(&vi,&vc,&op);

	wfx->wFormatTag = WAVE_FORMAT_PCM;
	wfx->nChannels = vi.channels;
	wfx->wBitsPerSample = 16;
	wfx->nSamplesPerSec = vi.rate;
	wfx->nBlockAlign = wfx->nChannels * (wfx->wBitsPerSample/8);
	wfx->nAvgBytesPerSec = wfx->nSamplesPerSec * wfx->nBlockAlign;
	wfx->cbSize = 0;

	ogg_sync_clear(&oy);
	ogg_stream_clear(&os);
	vorbis_comment_clear(&vc);
	vorbis_info_clear(&vi);
	return TRUE;
}
	StreamEncoder::StreamEncoder()
	{
		//Initialize the info 
		vorbis_info_init(&mVorbisInfo);

		if (ErrorCheck(vorbis_encode_init(&mVorbisInfo, 2, 44100, 100, 80, 60)) == true)
		{
			//Error
			Write("vorbis_encode_init error");
			return;
		}

		if (ErrorCheck(vorbis_analysis_init(&mVorbisDspState, &mVorbisInfo)) == true)
		{
			//Error
			Write("vorbis_analysis_init error");
			return;
		}

		vorbis_comment_init(&mVorbisComment);
		//vorbis_comment_add(&mVorbisComment, "Comments");
		int vahCode = vorbis_analysis_headerout(&mVorbisDspState, &mVorbisComment, &mOggPacketIdentification, &mOggPacketComment, &mOggPacketCodes);
		if (ErrorCheck(vahCode) == true)
		{
			//Error
			Write("vorbis_analysis_init error");
			return;
		}

		if (ErrorCheck(vorbis_block_init(&mVorbisDspState, &mVorbisBlock)) == true)
		{
			//Error
			Write("vorbis_block_init error");
			return;
		}
	}
Exemple #7
0
void EncoderVorbis::initStream() {
    // set up analysis state and auxiliary encoding storage
    vorbis_analysis_init(&m_vdsp, &m_vinfo);
    vorbis_block_init(&m_vdsp, &m_vblock);

    // set up packet-to-stream encoder; attach a random serial number
    srand(time(0));
    ogg_stream_init(&m_oggs, getSerial());

    // add comment
    vorbis_comment_init(&m_vcomment);
    vorbis_comment_add_tag(&m_vcomment, "ENCODER", "mixxx/libvorbis");
    if (m_metaDataArtist != NULL) {
        vorbis_comment_add_tag(&m_vcomment, "ARTIST", m_metaDataArtist);
    }
    if (m_metaDataTitle != NULL) {
        vorbis_comment_add_tag(&m_vcomment, "TITLE", m_metaDataTitle);
    }
    if (m_metaDataAlbum != NULL) {
        vorbis_comment_add_tag(&m_vcomment, "ALBUM", m_metaDataAlbum);
    }

    // set up the vorbis headers
    ogg_packet headerInit;
    ogg_packet headerComment;
    ogg_packet headerCode;
    vorbis_analysis_headerout(&m_vdsp, &m_vcomment, &headerInit, &headerComment, &headerCode);
    ogg_stream_packetin(&m_oggs, &headerInit);
    ogg_stream_packetin(&m_oggs, &headerComment);
    ogg_stream_packetin(&m_oggs, &headerCode);

    // The encoder is now inialized. The encode method will start streaming by
    // sending the header first.
    m_header_write = true;
    m_bStreamInitialized = true;
}
Exemple #8
0
BOOL ovd_reparse_stream(ovd_stream_buf* buf)
{
	ovd_handle* handle = (ovd_handle*)buf->handle;

	if (buf->len) {
		ogg_sync_wrote(handle->oy, buf->len);
		int result = ogg_sync_pageout(handle->oy, &handle->og);
		if (result == 0) {
			buf->len = OVD_STREAM_BUF_LEN;
			return TRUE;
		}
		else if (result < 0)
			return FALSE;
	}

//	ogg_stream_init(&handle->os, ogg_page_serialno(&handle->og));
	handle->os = ogg_stream_create(ogg_page_serialno(&handle->og));
	vorbis_info_init(&handle->vi);
    vorbis_comment_init(&handle->vc);
	if (ogg_stream_pagein(handle->os, &handle->og) < 0)
		return FALSE;

	if (ogg_stream_packetout(handle->os,&handle->op) != 1)
		return FALSE;

	if (vorbis_synthesis_headerin(&handle->vi, &handle->vc, &handle->op) < 0)
		return FALSE;

	handle->init = 0;
	handle->eof = 0;
	ovd_header_init(handle);

	buf->buf = ogg_sync_bufferin(handle->oy, OVD_STREAM_BUF_LEN);
	buf->len = OVD_STREAM_BUF_LEN;
	return TRUE;
}
Exemple #9
0
static stream_processor *
find_stream_processor (stream_set *set, ogg_page *page)
{	uint32_t serial = ogg_page_serialno (page) ;
	int i, invalid = 0 ;

	stream_processor *stream ;

	for (i = 0 ; i < set->used ; i++)
	{	if (serial == set->streams [i].serial)
		{	/* We have a match! */
			stream = & (set->streams [i]) ;

			set->in_headers = 0 ;
			/* if we have detected EOS, then this can't occur here. */
			if (stream->end)
			{	stream->isillegal = 1 ;
				return stream ;
			}

			stream->isnew = 0 ;
			stream->end = ogg_page_eos (page) ;
			stream->serial = serial ;
			return stream ;
		} ;
	} ;

	/* If there are streams open, and we've reached the end of the
	** headers, then we can't be starting a new stream.
	** XXX: might this sometimes catch ok streams if EOS flag is missing,
	** but the stream is otherwise ok?
	*/
	if (streams_open (set) && !set->in_headers)
		invalid = 1 ;

	set->in_headers = 1 ;

	if (set->allocated < set->used)
		stream = &set->streams [set->used] ;
	else
	{	set->allocated += 5 ;
		set->streams = realloc (set->streams, sizeof (stream_processor) * set->allocated) ;
		stream = &set->streams [set->used] ;
	} ;

	set->used++ ;

	stream->isnew = 1 ;
	stream->isillegal = invalid ;

	{	int res ;
		ogg_packet packet ;

		/* We end up processing the header page twice, but that's ok. */
		ogg_stream_init (&stream->ostream, serial) ;
		ogg_stream_pagein (&stream->ostream, page) ;
		res = ogg_stream_packetout (&stream->ostream, &packet) ;
		if (res <= 0)
			return NULL ;
		else if (packet.bytes >= 7 && memcmp (packet.packet, "\x01vorbis", 7) == 0)
		{	stream->lastgranulepos = 0 ;
			vorbis_comment_init (&stream->vcomment) ;
			vorbis_info_init (&stream->vinfo) ;
		} ;

		res = ogg_stream_packetout (&stream->ostream, &packet) ;

		/* re-init, ready for processing */
		ogg_stream_clear (&stream->ostream) ;
		ogg_stream_init (&stream->ostream, serial) ;
	}

	stream->end = ogg_page_eos (page) ;
	stream->serial = serial ;

	return stream ;
} /* find_stream_processor */
Exemple #10
0
static int
vorbis_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
{	OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
	VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
	int k, ret ;

	vorbis_info_init (&vdata->vinfo) ;

	/* The style of encoding should be selectable here, VBR quality mode. */
	ret = vorbis_encode_init_vbr (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, vdata->quality) ;

#if 0
	ret = vorbis_encode_init (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, -1, 128000, -1) ; /* average bitrate mode */
	ret = (	vorbis_encode_setup_managed (&vdata->vinfo, psf->sf.channels, psf->sf.samplerate, -1, 128000, -1)
					|| vorbis_encode_ctl (&vdata->vinfo, OV_ECTL_RATEMANAGE_AVG, NULL)
					|| vorbis_encode_setup_init (&vdata->vinfo)
				) ;
#endif
	if (ret)
		return SFE_BAD_OPEN_FORMAT ;

	vdata->loc = 0 ;

	/* add a comment */
	vorbis_comment_init (&vdata->vcomment) ;

	vorbis_comment_add_tag (&vdata->vcomment, "ENCODER", "libsndfile") ;
	for (k = 0 ; k < SF_MAX_STRINGS ; k++)
	{	const char * name ;

		if (psf->strings.data [k].type == 0)
			break ;

		switch (psf->strings.data [k].type)
		{	case SF_STR_TITLE :
				name = "TITLE" ;
				break ;
			case SF_STR_COPYRIGHT :
				name = "COPYRIGHT" ;
				break ;
			case SF_STR_SOFTWARE :
				name = "SOFTWARE" ;
				break ;
			case SF_STR_ARTIST :
				name = "ARTIST" ;
				break ;
			case SF_STR_COMMENT :
				name = "COMMENT" ;
				break ;
			case SF_STR_DATE :
				name = "DATE" ;
				break ;
			case SF_STR_ALBUM :
				name = "ALBUM" ;
				break ;
			case SF_STR_LICENSE :
				name = "LICENSE" ;
				break ;
			case SF_STR_TRACKNUMBER :
				name = "Tracknumber" ;
				break ;
			case SF_STR_GENRE :
				name = "Genre" ;
				break ;

			default :
				continue ;
		} ;

		vorbis_comment_add_tag (&vdata->vcomment, name, psf->strings.storage + psf->strings.data [k].offset) ;
	} ;

	/* set up the analysis state and auxiliary encoding storage */
	vorbis_analysis_init (&vdata->vdsp, &vdata->vinfo) ;
	vorbis_block_init (&vdata->vdsp, &vdata->vblock) ;

	/*
	**	Set up our packet->stream encoder.
	**	Pick a random serial number ; that way we can more likely build
	**	chained streams just by concatenation.
	*/

	ogg_stream_init (&odata->ostream, psf_rand_int32 ()) ;

	/* 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 ;
		int result ;

		vorbis_analysis_headerout (&vdata->vdsp, &vdata->vcomment, &header, &header_comm, &header_code) ;
		ogg_stream_packetin (&odata->ostream, &header) ; /* automatically placed in its own page */
		ogg_stream_packetin (&odata->ostream, &header_comm) ;
		ogg_stream_packetin (&odata->ostream, &header_code) ;

		/* This ensures the actual
		 * audio data will start on a new page, as per spec
		 */
		while ((result = ogg_stream_flush (&odata->ostream, &odata->opage)) != 0)
		{	psf_fwrite (odata->opage.header, 1, odata->opage.header_len, psf) ;
			psf_fwrite (odata->opage.body, 1, odata->opage.body_len, psf) ;
		} ;
	}

	return 0 ;
} /* vorbis_write_header */
Exemple #11
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 */
Exemple #12
0
// Just create the Quicktime objects since this routine is also called
// for reopening.
int FileVorbis::open_file(int rd, int wr)
{
	int result = 0;
	this->rd = rd;
	this->wr = wr;

//printf("FileVorbis::open_file 1\n");
	if(rd)
	{
//printf("FileVorbis::open_file 1\n");
		if(!(fd = fopen(asset->path, "rb")))
		{
			eprintf("Error while opening \"%s\" for reading. \n%m\n", asset->path);
			result = 1;
		}
		else
		{
//printf("FileVorbis::open_file 2 %p %p\n", fd, vf);
			if(ov_open(fd, &vf, NULL, 0) < 0)
			{
				eprintf("Invalid bitstream in %s\n", asset->path);
				result = 1;
			}
			else
			{
//printf("FileVorbis::open_file 1\n");
				vorbis_info *vi = ov_info(&vf, -1);
				asset->channels = vi->channels;
				if(!asset->sample_rate)
					asset->sample_rate = vi->rate;
//printf("FileVorbis::open_file 1\n");
				asset->audio_length = ov_pcm_total(&vf,-1);
//printf("FileVorbis::open_file 1\n");
				asset->audio_data = 1;
// printf("FileVorbis::open_file 1 %d %d %d\n", 
// asset->channels, 
// asset->sample_rate, 
// asset->audio_length);
			}
		}
	}

	if(wr)
	{
		if(!(fd = fopen(asset->path, "wb")))
		{
			eprintf("Error while opening \"%s\" for writing. \n%m\n", asset->path);
			result = 1;
		}
		else
		{
			vorbis_info_init(&vi);
			if(!asset->vorbis_vbr)
				result = vorbis_encode_init(&vi, 
					asset->channels, 
					asset->sample_rate, 
					asset->vorbis_max_bitrate, 
					asset->vorbis_bitrate, 
					asset->vorbis_min_bitrate);
			else
			{
				result = vorbis_encode_setup_managed(&vi,
					asset->channels, 
					asset->sample_rate, 
					asset->vorbis_max_bitrate, 
					asset->vorbis_bitrate, 
					asset->vorbis_min_bitrate);
				result |= vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_AVG, NULL);
				result |= vorbis_encode_setup_init(&vi);
			}

			if(!result)
			{
				vorbis_analysis_init(&vd, &vi);
				vorbis_block_init(&vd, &vb);
				vorbis_comment_init(&vc);
				srand(time(NULL));
				ogg_stream_init(&os, rand());

				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);

				while(1)
				{
					int result = ogg_stream_flush(&os, &og);
					if(result == 0) break;
					fwrite(og.header, 1, og.header_len, fd);
					fwrite(og.body, 1, og.body_len, fd);
				}
			}
		}
	}

//printf("FileVorbis::open_file 2\n");
	return result;
}
Exemple #13
0
RefPtr<MediaDataDecoder::InitPromise>
VorbisDataDecoder::Init()
{
  vorbis_info_init(&mVorbisInfo);
  vorbis_comment_init(&mVorbisComment);
  PodZero(&mVorbisDsp);
  PodZero(&mVorbisBlock);

  AutoTArray<unsigned char*,4> headers;
  AutoTArray<size_t,4> headerLens;
  if (!XiphExtradataToHeaders(headers, headerLens,
                              mInfo.mCodecSpecificConfig->Elements(),
                              mInfo.mCodecSpecificConfig->Length())) {
    return InitPromise::CreateAndReject(
      MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                  RESULT_DETAIL("Could not get vorbis header.")),
      __func__);
  }
  for (size_t i = 0; i < headers.Length(); i++) {
    if (NS_FAILED(DecodeHeader(headers[i], headerLens[i]))) {
      return InitPromise::CreateAndReject(
        MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                    RESULT_DETAIL("Could not decode vorbis header.")),
        __func__);
    }
  }

  MOZ_ASSERT(mPacketCount == 3);

  int r = vorbis_synthesis_init(&mVorbisDsp, &mVorbisInfo);
  if (r) {
    return InitPromise::CreateAndReject(
      MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                  RESULT_DETAIL("Systhesis init fail.")),
      __func__);
  }

  r = vorbis_block_init(&mVorbisDsp, &mVorbisBlock);
  if (r) {
    return InitPromise::CreateAndReject(
      MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                  RESULT_DETAIL("Block init fail.")),
      __func__);
  }

  if (mInfo.mRate != (uint32_t)mVorbisDsp.vi->rate) {
    LOG(LogLevel::Warning,
        ("Invalid Vorbis header: container and codec rate do not match!"));
  }
  if (mInfo.mChannels != (uint32_t)mVorbisDsp.vi->channels) {
    LOG(LogLevel::Warning,
        ("Invalid Vorbis header: container and codec channels do not match!"));
  }

  AudioConfig::ChannelLayout layout(mVorbisDsp.vi->channels);
  if (!layout.IsValid()) {
    return InitPromise::CreateAndReject(
      MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR,
                  RESULT_DETAIL("Invalid audio layout.")),
      __func__);
  }

  return InitPromise::CreateAndResolve(TrackInfo::kAudioTrack, __func__);
}
Exemple #14
0
static int init(sh_audio_t *sh)
{
  unsigned int offset, i, length, hsizes[3];
  void *headers[3];
  unsigned char* extradata;
  ogg_packet op;
  vorbis_comment vc;
  struct ov_struct_st *ov;
#define ERROR() { \
    vorbis_comment_clear(&vc); \
    vorbis_info_clear(&ov->vi); \
    free(ov); \
    return 0; \
  }

  /// Init the decoder with the 3 header packets
  ov = malloc(sizeof(struct ov_struct_st));
  vorbis_info_init(&ov->vi);
  vorbis_comment_init(&vc);

  if(! sh->wf) {
    mp_msg(MSGT_DECAUDIO,MSGL_ERR,"ad_vorbis, extradata seems to be absent! exit\n");
    ERROR();
  }

  if(! sh->wf->cbSize) {
    mp_msg(MSGT_DECAUDIO,MSGL_ERR,"ad_vorbis, extradata seems to be absent!, exit\n");
    ERROR();
  }

  mp_msg(MSGT_DECAUDIO,MSGL_V,"ad_vorbis, extradata seems is %d bytes long\n", sh->wf->cbSize);
  extradata = (char*) (sh->wf+1);

  if(*extradata != 2) {
    mp_msg (MSGT_DEMUX, MSGL_WARN, "ad_vorbis: Vorbis track does not contain valid headers.\n");
    ERROR();
  }

  offset = 1;
  for (i=0; i < 2; i++) {
    length = 0;
    while ((extradata[offset] == (unsigned char) 0xFF) && length < sh->wf->cbSize) {
      length += 255;
      offset++;
    }
    if(offset >= (sh->wf->cbSize - 1)) {
      mp_msg (MSGT_DEMUX, MSGL_WARN, "ad_vorbis: Vorbis track does not contain valid headers.\n");
      ERROR();
    }
    length += extradata[offset];
    offset++;
    mp_msg (MSGT_DEMUX, MSGL_V, "ad_vorbis, offset: %u, length: %u\n", offset, length);
    hsizes[i] = length;
  }

  headers[0] = &extradata[offset];
  headers[1] = &extradata[offset + hsizes[0]];
  headers[2] = &extradata[offset + hsizes[0] + hsizes[1]];
  hsizes[2] = sh->wf->cbSize - offset - hsizes[0] - hsizes[1];
  mp_msg (MSGT_DEMUX, MSGL_V, "ad_vorbis, header sizes: %d %d %d\n", hsizes[0], hsizes[1], hsizes[2]);

  for(i=0; i<3; i++) {
    op.bytes = hsizes[i];
    op.packet = headers[i];
    op.b_o_s  = (i == 0);
    if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {
      mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: header n. %d broken! len=%ld\n", i, op.bytes);
      ERROR();
    }
    if(i == 2) {
      float rg_gain=0.f, rg_peak=0.f;
    char **ptr=vc.user_comments;
    while(*ptr){
      mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbisComment: %s\n",*ptr);
      /* replaygain */
      read_vorbis_comment( *ptr, "replaygain_album_gain=", "%f", &rg_gain );
      read_vorbis_comment( *ptr, "rg_audiophile=", "%f", &rg_gain );
      if( !rg_gain ) {
	read_vorbis_comment( *ptr, "replaygain_track_gain=", "%f", &rg_gain );
	read_vorbis_comment( *ptr, "rg_radio=", "%f", &rg_gain );
      }
      read_vorbis_comment( *ptr, "replaygain_album_peak=", "%f", &rg_peak );
      if( !rg_peak ) {
	read_vorbis_comment( *ptr, "replaygain_track_peak=", "%f", &rg_peak );
	read_vorbis_comment( *ptr, "rg_peak=", "%f", &rg_peak );
      }
      ++ptr;
    }
    /* replaygain: scale */
    if(!rg_gain)
      ov->rg_scale = 1.f; /* just in case pow() isn't standard-conformant */
    else
      ov->rg_scale = pow(10.f, rg_gain/20);
    /* replaygain: anticlip */
    if(ov->rg_scale * rg_peak > 1.f)
      ov->rg_scale = 1.f / rg_peak;
    /* replaygain: security */
    if(ov->rg_scale > 15.)
      ov->rg_scale = 15.;
#ifdef CONFIG_TREMOR
    ov->rg_scale_int = (int)(ov->rg_scale*64.f);
#endif
    mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Bitstream is %d channel%s, %dHz, %dbit/s %cBR\n",(int)ov->vi.channels,ov->vi.channels>1?"s":"",(int)ov->vi.rate,(int)ov->vi.bitrate_nominal,
	(ov->vi.bitrate_lower!=ov->vi.bitrate_nominal)||(ov->vi.bitrate_upper!=ov->vi.bitrate_nominal)?'V':'C');
    if(rg_gain || rg_peak)
      mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Gain = %+.2f dB, Peak = %.4f, Scale = %.2f\n", rg_gain, rg_peak, ov->rg_scale);
    mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Encoded by: %s\n",vc.vendor);
    }
  }

  vorbis_comment_clear(&vc);

//  printf("lower=%d  upper=%d  \n",(int)ov->vi.bitrate_lower,(int)ov->vi.bitrate_upper);

  // Setup the decoder
  sh->channels=ov->vi.channels;
  sh->samplerate=ov->vi.rate;
  sh->samplesize=2;
  // assume 128kbit if bitrate not specified in the header
  sh->i_bps=((ov->vi.bitrate_nominal>0) ? ov->vi.bitrate_nominal : 128000)/8;
  sh->context = ov;

  /// Finish the decoder init
  vorbis_synthesis_init(&ov->vd,&ov->vi);
  vorbis_block_init(&ov->vd,&ov->vb);
  mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Init OK!\n");

  return 1;
}
Exemple #15
0
int input_calculate_ogg_sleep(ogg_page *page)
{
    static ogg_stream_state os;
    ogg_packet op;
    static vorbis_info vi;
    static vorbis_comment vc;
    static int need_start_pos, need_headers, state_in_use = 0;
    static int serialno = 0;
    static uint64_t offset;
    static uint64_t first_granulepos;

    if (ogg_page_granulepos(page) == -1)
    {
        LOG_ERROR0("Timing control: corrupt timing information in vorbis file, cannot stream.");
        return -1;
    }
    if (ogg_page_bos (page))
    {
        control.oldsamples = 0;

        if (state_in_use)
            ogg_stream_clear (&os);
        ogg_stream_init (&os, ogg_page_serialno (page));
        serialno = ogg_page_serialno (page);
        state_in_use = 1;
        vorbis_info_init (&vi);
        vorbis_comment_init (&vc);
        need_start_pos = 1;
        need_headers = 3;
        offset = (uint64_t)0;
    }
    if (need_start_pos)
    {
        int found_first_granulepos = 0;

        ogg_stream_pagein (&os, page);
        while (ogg_stream_packetout (&os, &op) == 1)
        {
            if (need_headers)
            {
                if (vorbis_synthesis_headerin (&vi, &vc, &op) < 0)
                {
                    LOG_ERROR0("Timing control: can't determine sample rate for input, not vorbis.");
                    control.samplerate = 0;
                    return -1;
                }
                need_headers--;
                control.samplerate = vi.rate;

                if (need_headers == 0)
                {
                    vorbis_comment_clear (&vc);
                    first_granulepos = (uint64_t)0;
                    return 0;
                }
                continue;
            }
            /* headers have been read */
            if (first_granulepos == 0 && op.granulepos > 0)
            {
                first_granulepos = op.granulepos;
                found_first_granulepos = 1;
            }
            offset += vorbis_packet_blocksize (&vi, &op) / 4;
        }
        if (!found_first_granulepos)
            return 0;

        need_start_pos = 0;
        control.oldsamples = first_granulepos - offset;
        vorbis_info_clear (&vi);
        ogg_stream_clear (&os);
        state_in_use = 0;
    }
    if (serialno != ogg_page_serialno (page))
    {
        LOG_ERROR0 ("Found page which does not belong to current logical stream");
        return -1;
    }
    control.samples = ogg_page_granulepos (page) - control.oldsamples;
    control.oldsamples = ogg_page_granulepos (page);

    control.senttime += ((uint64_t)control.samples * 1000000 /
            (uint64_t)control.samplerate);

    return 0;
}
S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname)
{
#define READ_BUFFER 1024
	unsigned char readbuffer[READ_BUFFER*4+44];   /* out of the data segment, not the stack */	/*Flawfinder: ignore*/

	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;
	int result;

	U16 num_channels = 0;
	U32 sample_rate = 0;
	U32 bits_per_sample = 0;

	S32 format_error = 0;
	std::string error_msg;
	if ((format_error = check_for_invalid_wav_formats(in_fname, error_msg)))
	{
		llwarns << error_msg << ": " << in_fname << llendl;
		return(format_error);
	}

#if 1
	unsigned char wav_header[44];	/*Flawfinder: ignore*/

	S32 data_left = 0;

	LLAPRFile infile ;
	infile.open(in_fname,LL_APR_RB);
	if (!infile.getFileHandle())
	{
		llwarns << "Couldn't open temporary ogg file for writing: " << in_fname
			<< llendl;
		return(LLVORBISENC_SOURCE_OPEN_ERR);
	}

	LLAPRFile outfile ;
	outfile.open(out_fname,LL_APR_WPB);
	if (!outfile.getFileHandle())
	{
		llwarns << "Couldn't open upload sound file for reading: " << in_fname
			<< llendl;
		return(LLVORBISENC_DEST_OPEN_ERR);
	}
	
	 // parse the chunks
	 U32 chunk_length = 0;
	 U32 file_pos = 12;  // start at the first chunk (usually fmt but not always)
	 
	 while (infile.eof() != APR_EOF)
	 {
		 infile.seek(APR_SET,file_pos);
		 infile.read(wav_header, 44);
		 
		 chunk_length = ((U32) wav_header[7] << 24) 
			 + ((U32) wav_header[6] << 16) 
			 + ((U32) wav_header[5] << 8) 
			 + wav_header[4];
		 
//		 llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl;
		 
		 if (!(strncmp((char *)&(wav_header[0]),"fmt ",4)))
		 {
			 num_channels = ((U16) wav_header[11] << 8) + wav_header[10];
			 sample_rate = ((U32) wav_header[15] << 24) 
				 + ((U32) wav_header[14] << 16) 
				 + ((U32) wav_header[13] << 8) 
				 + wav_header[12];
			 bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22];
		 }
	 	 else if (!(strncmp((char *)&(wav_header[0]),"data",4)))
		 {
			 infile.seek(APR_SET,file_pos+8);
			 // leave the file pointer at the beginning of the data chunk data
			 data_left = chunk_length;			
			 break;
		 }
		 file_pos += (chunk_length + 8);
		 chunk_length = 0;
	 } 
	 

	 /********** Encode setup ************/
	 
	 /* choose an encoding mode */
	 /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
	 vorbis_info_init(&vi);

	 // always encode to mono

	 // SL-52913 & SL-53779 determined this quality level to be our 'good
	 // enough' general-purpose quality level with a nice low bitrate.
	 // Equivalent to oggenc -q0.5
	 F32 quality = 0.05f;
//	 quality = (bitrate==128000 ? 0.4f : 0.1);

//	 if (vorbis_encode_init(&vi, /* num_channels */ 1 ,sample_rate, -1, bitrate, -1))
	 if (vorbis_encode_init_vbr(&vi, /* num_channels */ 1 ,sample_rate, quality))
//	 if (vorbis_encode_setup_managed(&vi,1,sample_rate,-1,bitrate,-1) ||
//		vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE_AVG,NULL) ||
//		vorbis_encode_setup_init(&vi))
	{
		llwarns << "unable to initialize vorbis codec at quality " << quality << llendl;
		//		llwarns << "unable to initialize vorbis codec at bitrate " << bitrate << llendl;
		return(LLVORBISENC_DEST_OPEN_ERR);
	}
	 
	 /* add a comment */
	 vorbis_comment_init(&vc);
//	 vorbis_comment_add(&vc,"Linden");
	 
	 /* 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 */
	 ogg_stream_init(&os, ll_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);
		 
		 /* We don't have to write out here, but doing so makes streaming 
		  * much easier, so we do, flushing ALL pages. This ensures the actual
		  * audio data will start on a new page
		  */
		 while(!eos){
			 int result=ogg_stream_flush(&os,&og);
			 if(result==0)break;
			 outfile.write(og.header, og.header_len);
			 outfile.write(og.body, og.body_len);
		 }
		 
	 }
	 
	 
	 while(!eos)
	 {
		 long bytes_per_sample = bits_per_sample/8;

		 long bytes=(long)infile.read(readbuffer,llclamp((S32)(READ_BUFFER*num_channels*bytes_per_sample),0,data_left)); /* stereo hardwired here */
		 
		 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);
//			 eos = 1;
			 
		 }
		 else
		 {
			 long i;
			 long samples;
			 int temp;

			 data_left -= bytes;
             /* data to encode */
			 
			 /* expose the buffer to submit data */
			 float **buffer=vorbis_analysis_buffer(&vd,READ_BUFFER);
			
			 i = 0;
			 samples = bytes / (num_channels * bytes_per_sample);

			 if (num_channels == 2)
			 {
				 if (bytes_per_sample == 2)
				 {
					 /* uninterleave samples */
					 for(i=0; i<samples ;i++)
					 {
					 	 temp =  ((signed char *)readbuffer)[i*4+1];	/*Flawfinder: ignore*/
						 temp += ((signed char *)readbuffer)[i*4+3];	/*Flawfinder: ignore*/
						 temp <<= 8;
						 temp += readbuffer[i*4];
						 temp += readbuffer[i*4+2];

						 buffer[0][i] = ((float)temp) / 65536.f;
					 }
				 }
				 else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard")
				 {
					 /* uninterleave samples */
					 for(i=0; i<samples ;i++)
					 {
					 	 temp  = readbuffer[i*2+0];
						 temp += readbuffer[i*2+1];
						 temp -= 256;
						 buffer[0][i] = ((float)temp) / 256.f;
					 }
				 } 
			 }
			 else if (num_channels == 1)
			 {
				 if (bytes_per_sample == 2)
				 {
					 for(i=0; i < samples ;i++)
					 {
					 	 temp = ((signed char*)readbuffer)[i*2+1];
						 temp <<= 8;
						 temp += readbuffer[i*2];
						 buffer[0][i] = ((float)temp) / 32768.f;
					 }
				 }
				 else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard")
				 {
					 for(i=0; i < samples ;i++)
					 {
						 temp = readbuffer[i];
						 temp -= 128;
						 buffer[0][i] = ((float)temp) / 128.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 */
			/* Do the main analysis, creating a packet */
			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)
			 {
				 result = ogg_stream_pageout(&os,&og);

				 if(result==0)
				 	break;

				 outfile.write(og.header, og.header_len);
				 outfile.write(og.body, og.body_len);
				 
				 /* 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,"Vorbis encoding: Done.\n");
	 llinfos << "Vorbis encoding: Done." << llendl;
	 
#endif
	 return(LLVORBISENC_NOERR);
	 
}
Exemple #17
0
static int _fetch_headers(OggVorbis_File *vf,
			  vorbis_info *vi,
			  vorbis_comment *vc,
			  ogg_uint32_t *serialno,
			  ogg_page *og_ptr){
  ogg_page og={0,0,0,0};
  ogg_packet op={0,0,0,0,0,0};
  int i,ret;
  
  if(!og_ptr){
    ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
    if(llret==OV_EREAD)return(OV_EREAD);
    if(llret<0)return OV_ENOTVORBIS;
    og_ptr=&og;
  }

  ogg_stream_reset_serialno(vf->os,ogg_page_serialno(og_ptr));
  if(serialno)*serialno=vf->os->serialno;
  vf->ready_state=STREAMSET;
  
  /* extract the initial header from the first page and verify that the
     Ogg bitstream is in fact Vorbis data */
  
  vorbis_info_init(vi);
  vorbis_comment_init(vc);
  
  i=0;
  while(i<3){
    ogg_stream_pagein(vf->os,og_ptr);
    while(i<3){
      int result=ogg_stream_packetout(vf->os,&op);
      if(result==0)break;
      if(result==-1){
	ret=OV_EBADHEADER;
	goto bail_header;
      }
      if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
	goto bail_header;
      }
      i++;
    }
    if(i<3)
      if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
	ret=OV_EBADHEADER;
	goto bail_header;
      }
  }

  ogg_packet_release(&op);
  ogg_page_release(&og);
  return 0; 

 bail_header:
  ogg_packet_release(&op);
  ogg_page_release(&og);
  vorbis_info_clear(vi);
  vorbis_comment_clear(vc);
  vf->ready_state=OPENED;

  return ret;
}
void probe_ogg(info_t *ipipe)
{
    ogg_sync_state    sync;
    ogg_page          page;
    ogg_packet        pack;
    char             *buf;
    int               nread, np, sno, nvtracks = 0, natracks = 0, i, idx;
    //int               endofstream = 0, k, n;
    struct demux_t    streams[MAX_AUDIO_TRACKS + MAX_VIDEO_TRACKS];
    int               fdin = -1;
    char vid_codec[5];
    ogm_stream_header *sth;

    fdin = ipipe->fd_in;

    if (fdin == -1) {
	tc_log_error(__FILE__, "Could not open file.");
	goto ogg_out;
    }

    ipipe->probe_info->magic=TC_MAGIC_OGG;

    memset(streams, 0, sizeof(streams));
    for (i = 0; i < (MAX_AUDIO_TRACKS + MAX_VIDEO_TRACKS); i++)
	streams[i].serial = -1;

    ogg_sync_init(&sync);

    while (1) {
	np = ogg_sync_pageseek(&sync, &page);
	if (np < 0) {
	    tc_log_error(__FILE__, "ogg_sync_pageseek failed");
	    goto ogg_out;
	}
	if (np == 0) {
	    buf = ogg_sync_buffer(&sync, BLOCK_SIZE);
	    if (!buf) {
		tc_log_error(__FILE__, "ogg_sync_buffer failed");
		goto ogg_out;
	    }

	    if ((nread = read(fdin, buf, BLOCK_SIZE)) <= 0) {
	    }
	    ogg_sync_wrote(&sync, nread);
	    continue;
	}

	if (!ogg_page_bos(&page)) {
	    break;
	} else {
	    ogg_stream_state sstate;
	    vorbis_info *inf = tc_malloc (sizeof(vorbis_info));
	    vorbis_comment *com = tc_malloc (sizeof(vorbis_comment));

	    if (!inf || !com) {
		tc_log_error(__FILE__, "Out of Memory at %d", __LINE__);
		goto ogg_out;
	    }
	    sno = ogg_page_serialno(&page);
	    if (ogg_stream_init(&sstate, sno)) {
		tc_log_error(__FILE__, "ogg_stream_init failed");
		goto ogg_out;
	    }
	    ogg_stream_pagein(&sstate, &page);
	    ogg_stream_packetout(&sstate, &pack);

	    switch (ogm_packet_type(pack))
	    {
		case Vorbis:
		    vorbis_info_init(inf);
		    vorbis_comment_init(com);

		    if(vorbis_synthesis_headerin(inf, com, &pack) < 0) {
			tc_log_warn(__FILE__, "Could not decode vorbis header "
				    "packet - invalid vorbis stream ()");
		    } else {
#ifdef OGM_DEBUG
			tc_log_msg(__FILE__, "(a%d/%d) Vorbis audio; "
				"rate: %ldHz, channels: %d, bitrate %3.2f kb/s",
				natracks + 1, natracks + nvtracks + 1, inf->rate,
				inf->channels, (double)inf->bitrate_nominal/1000.0);
#endif

			ipipe->probe_info->track[natracks].samplerate = inf->rate;
			ipipe->probe_info->track[natracks].chan = inf->channels;
			ipipe->probe_info->track[natracks].bits = 0; /* XXX --tibit*/
			ipipe->probe_info->track[natracks].format = TC_CODEC_VORBIS;
			ipipe->probe_info->track[natracks].bitrate = (double)inf->bitrate_nominal/1000.0;

			ipipe->probe_info->track[natracks].tid=natracks;
			if(ipipe->probe_info->track[natracks].chan>0) ++ipipe->probe_info->num_tracks;

			streams[natracks].serial = sno;
			streams[natracks].vorbis = 1;
			ac_memcpy(&streams[natracks].state, &sstate, sizeof(sstate));
			natracks++;
		    }
		    break;
#ifdef HAVE_THEORA
		case Theora:
		{
		    theora_info ti;
		    theora_comment tc;

		    theora_decode_header(&ti, &tc, &pack);

		    ipipe->probe_info->width  =  ti.width;
		    ipipe->probe_info->height =  ti.height;
		    ipipe->probe_info->fps    =  (double)ti.fps_numerator/ti.fps_denominator;
		    tc_frc_code_from_ratio(&(ipipe->probe_info->frc),
		    	    		   ti.fps_numerator, ti.fps_denominator);

		    ipipe->probe_info->codec=TC_CODEC_THEORA;

		    idx = natracks + MAX_AUDIO_TRACKS;

		    streams[idx].serial = sno;
		    ac_memcpy(&streams[idx].state, &sstate, sizeof(sstate));
		    nvtracks++;
		    break;
	        }
#endif
		case DirectShow:
		    if ((*(int32_t*)(pack.packet+96) == 0x05589f80) &&
			    (pack.bytes >= 184)) {
			tc_log_warn(__FILE__, "(v%d/%d) Found old video "
				    "header. Not supported.", nvtracks + 1,
				    natracks + nvtracks + 1);
		    } else if (*(int32_t*)pack.packet+96 == 0x05589F81) {
			tc_log_warn(__FILE__, "(a%d/%d) Found old audio "
				    "header. Not supported.", natracks + 1,
				    natracks + nvtracks + 1);
		    }
		    break;
		case StreamHeader:
		    sth = (ogm_stream_header *)(pack.packet + 1);

		    if (!strncmp(sth->streamtype, "video", 5)) {
#ifdef OGM_DEBUG
			unsigned long codec;
			codec = (sth->subtype[0] << 24) +
			    (sth->subtype[1] << 16) + (sth->subtype[2] << 8) + sth->subtype[3];
			tc_log_msg(__FILE__, "(v%d/%d) video; fps: %.3f width height: %dx%d "
				"codec: %p (%c%c%c%c)", nvtracks + 1,
				natracks + nvtracks + 1,
				(double)10000000 / (double)sth->time_unit,
				sth->sh.video.width, sth->sh.video.height, (void *)codec,
				sth->subtype[0], sth->subtype[1], sth->subtype[2],
				sth->subtype[3]);
#endif
			vid_codec[0] = sth->subtype[0];
			vid_codec[1] = sth->subtype[1];
			vid_codec[2] = sth->subtype[2];
			vid_codec[3] = sth->subtype[3];
			vid_codec[4] = '\0';

			//ipipe->probe_info->frames = AVI_video_frames(avifile);

			ipipe->probe_info->width  =  sth->sh.video.width;
			ipipe->probe_info->height =  sth->sh.video.height;
			ipipe->probe_info->fps    =  (double)10000000 / (double)sth->time_unit;
			tc_frc_code_from_value(&(ipipe->probe_info->frc),
  						  ipipe->probe_info->fps);

			ipipe->probe_info->codec=TC_CODEC_UNKNOWN; // gets rewritten

			if(strlen(vid_codec)==0) {
			    ipipe->probe_info->codec=TC_CODEC_RGB24;
			} else {

			    if(strcasecmp(vid_codec,"dvsd")==0)
				ipipe->probe_info->codec=TC_CODEC_DV;

			    if(strcasecmp(vid_codec,"DIV3")==0)
				ipipe->probe_info->codec=TC_CODEC_DIVX3;

			    if(strcasecmp(vid_codec,"DIVX")==0)
				ipipe->probe_info->codec=TC_CODEC_DIVX4;

			    if(strcasecmp(vid_codec,"DX50")==0)
				ipipe->probe_info->codec=TC_CODEC_DIVX5;

			    if(strcasecmp(vid_codec,"XVID")==0)
				ipipe->probe_info->codec=TC_CODEC_XVID;

			    if(strcasecmp(vid_codec,"MJPG")==0)
				ipipe->probe_info->codec=TC_CODEC_MJPEG;
			}

			idx = natracks + MAX_AUDIO_TRACKS;

			streams[idx].serial = sno;
			ac_memcpy(&streams[idx].state, &sstate, sizeof(sstate));
			nvtracks++;
		    } else if (!strncmp(sth->streamtype, "audio", 5)) {
			int codec;
			char buf[5];
			ac_memcpy(buf, sth->subtype, 4);
			buf[4] = 0;
			codec = strtoul(buf, NULL, 16);
#ifdef OGM_DEBUG
			tc_log_msg(__FILE__, "(a%d/%d) codec: %d (0x%04x) (%s) bits per "
				   "sample: %d channels: %hd  samples per second: %ld "
				   "avgbytespersec: %hd blockalign: %d",
				   natracks + 1, natracks + nvtracks + 1,
				   codec, codec,
				   codec == 0x1 ? "PCM" : codec == 55 ? "MP3" :
				   codec == 0x55 ? "MP3" :
				   codec == 0x2000 ? "AC3" : "unknown",
				   sth->bits_per_sample, sth->sh.audio.channels,
				   (long)sth->samples_per_unit,
				   sth->sh.audio.avgbytespersec,
				   sth->sh.audio.blockalign);
#endif
			idx = natracks;

			ipipe->probe_info->track[natracks].samplerate = sth->samples_per_unit;
			ipipe->probe_info->track[natracks].chan = sth->sh.audio.channels;
			ipipe->probe_info->track[natracks].bits =
			    (sth->bits_per_sample<4)?sth->bits_per_sample*8:sth->bits_per_sample;
			ipipe->probe_info->track[natracks].format = codec;
			ipipe->probe_info->track[natracks].bitrate = 0;

			ipipe->probe_info->track[natracks].tid=natracks;


			if(ipipe->probe_info->track[natracks].chan>0) ++ipipe->probe_info->num_tracks;

			streams[idx].serial = sno;
			ac_memcpy(&streams[idx].state, &sstate, sizeof(sstate));
			natracks++;
		    } else {
			tc_log_warn(__FILE__, "(%d) found new header of unknown/"
				"unsupported type\n", nvtracks + natracks + 1);
		    }
		    break;
		case none:
		    tc_log_warn(__FILE__, "OGG stream %d is of an unknown type "
			"(bad header?)", nvtracks + natracks + 1);
		    break;
	    } /* switch type */
	    free(inf);
	    free(com);
	    ogg_stream_clear(&sstate);
	} /* beginning of page */
    } /* while (1) */
ogg_out:
    //close(fdin);
    return;
}
int main(int argc,char *argv[]){

  int i,j;
  ogg_packet op;

  FILE *infile = stdin;

#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
  /* 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 );
#endif

  /* open the input file if any */
  if(argc==2){
    infile=fopen(argv[1],"rb");
    if(infile==NULL){
      fprintf(stderr,"Unable to open '%s' for playback.\n", argv[1]);
      exit(1);
    }
  }
  if(argc>2){
      usage();
      exit(1);
  }

  /* 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);

  /* Ogg file open; parse the headers */
  /* Only interested in Vorbis/Theora streams */
  while(!stateflag){
    int ret=buffer_data(infile,&oy);
    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 && theora_decode_header(&ti,&tc,&op)>=0){
        /* it is theora */
        memcpy(&to,&test,sizeof(test));
        theora_p=1;
      }else if(!vorbis_p && vorbis_synthesis_headerin(&vi,&vc,&op)>=0){
        /* it is vorbis */
        memcpy(&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");
        exit(1);
      }
      if(theora_decode_header(&ti,&tc,&op)){
        printf("Error parsing Theora stream headers; corrupt stream?\n");
        exit(1);
      }
      theora_p++;
      if(theora_p==3)break;
    }

    /* 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");
        exit(1);
      }
      if(vorbis_synthesis_headerin(&vi,&vc,&op)){
        fprintf(stderr,"Error parsing Vorbis stream headers; corrupt stream?\n");
        exit(1);
      }
      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(infile,&oy); /* someone needs more data */
      if(ret==0){
        fprintf(stderr,"End of file while searching for codec headers.\n");
        exit(1);
      }
    }
  }

  /* and now we have it all.  initialize decoders */
  if(theora_p){
    theora_decode_init(&td,&ti);
    printf("Ogg logical stream %x is Theora %dx%d %.02f fps video\n",
           (unsigned int)to.serialno,ti.width,ti.height, 
           (double)ti.fps_numerator/ti.fps_denominator);
    if(ti.width!=ti.frame_width || ti.height!=ti.frame_height)
      printf("  Frame content is %dx%d with offset (%d,%d).\n",
           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);
    fprintf(stderr,"Ogg logical stream %x is Vorbis %d channel %d Hz audio.\n",
            (unsigned int)vo.serialno,vi.channels,(int)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();

  /* install signal handler as SDL clobbered the default */
  signal (SIGINT, sigint_handler);

  /* on to the main decode loop.  We assume in this example that audio
     and video start roughly together, and don't begin playback until
     we have a start frame for both.  This is not necessarily a valid
     assumption in Ogg A/V streams! It will always be true of the
     example_encoder (and most streams) though. */

  stateflag=0; /* playback has not begun */
  while(!got_sigint){

    /* we want a video and audio frame ready to go at all times.  If
       we have to buffer incoming, buffer the compressed data (ie, let
       ogg do the buffering) */
    while(vorbis_p && !audiobuf_ready){
      int ret;
      float **pcm;

      /* if there's pending, decoded audio, grab it */
      if((ret=vorbis_synthesis_pcmout(&vd,&pcm))>0){
        int count=audiobuf_fill/2;
        int maxsamples=(audiofd_fragsize-audiobuf_fill)/2/vi.channels;
        for(i=0;i<ret && i<maxsamples;i++)
          for(j=0;j<vi.channels;j++){
            int val=rint(pcm[j][i]*32767.f);
            if(val>32767)val=32767;
            if(val<-32768)val=-32768;
            audiobuf[count++]=val;
          }
        vorbis_synthesis_read(&vd,i);
        audiobuf_fill+=i*vi.channels*2;
        if(audiobuf_fill==audiofd_fragsize)audiobuf_ready=1;
        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;
      }
    }

    while(theora_p && !videobuf_ready){
      /* theora is one in, one out... */
      if(ogg_stream_packetout(&to,&op)>0){

        theora_decode_packetin(&td,&op);
        videobuf_granulepos=td.granulepos;
        
        videobuf_time=theora_granule_time(&td,videobuf_granulepos);

        /* is it already too old to be useful?  This is only actually
           useful cosmetically after a SIGSTOP.  Note that we have to
           decode the frame even if we don't show it (for now) due to
           keyframing.  Soon enough libtheora will be able to deal
           with non-keyframe seeks.  */

        if(videobuf_time>=get_time())
        videobuf_ready=1;
                
      }else
        break;
    }

    if(!videobuf_ready && !audiobuf_ready && feof(infile))break;

    if(!videobuf_ready || !audiobuf_ready){
      /* no data yet for somebody.  Grab another page */
      int bytes=buffer_data(infile,&oy);
      while(ogg_sync_pageout(&oy,&og)>0){
        queue_page(&og);
      }
    }

    /* If playback has begun, top audio buffer off immediately. */
    if(stateflag) audio_write_nonblocking();

    /* are we at or past time for this video frame? */
    if(stateflag && videobuf_ready && videobuf_time<=get_time()){
      video_write();
      videobuf_ready=0;
    }

    if(stateflag &&
       (audiobuf_ready || !vorbis_p) &&
       (videobuf_ready || !theora_p) &&
       !got_sigint){
      /* we have an audio frame ready (which means the audio buffer is
         full), it's not time to play video, so wait until one of the
         audio buffer is ready or it's near time to play video */
        
      /* set up select wait on the audiobuffer and a timeout for video */
      struct timeval timeout;
      fd_set writefs;
      fd_set empty;
      int n=0;

      FD_ZERO(&writefs);
      FD_ZERO(&empty);
      if(audiofd>=0){
        FD_SET(audiofd,&writefs);
        n=audiofd+1;
      }

      if(theora_p){
        long milliseconds=(videobuf_time-get_time())*1000-5;
        if(milliseconds>500)milliseconds=500;
        if(milliseconds>0){
          timeout.tv_sec=milliseconds/1000;
          timeout.tv_usec=(milliseconds%1000)*1000;

          n=select(n,&empty,&writefs,&empty,&timeout);
          if(n)audio_calibrate_timer(0);
        }
      }else{
        select(n,&empty,&writefs,&empty,NULL);
      }
    }

    /* if our buffers either don't exist or are ready to go,
       we can begin playback */
    if((!theora_p || videobuf_ready) &&
       (!vorbis_p || audiobuf_ready))stateflag=1;
    /* same if we've run out of input */
    if(feof(infile))stateflag=1;

  }

  /* tear it all down */

  audio_close();
  SDL_Quit();

  if(vorbis_p){
    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);

  if(infile && infile!=stdin)fclose(infile);

  fprintf(stderr,
          "\r                                                              "
          "\nDone.\n");
  return(0);

}
Exemple #20
0
qboolean OGV_StartRead(cinematic_t *cin)
{
	int        status;
	ogg_page   og;
	ogg_packet op;
	int        i;

	cin->data = Com_Allocate(sizeof(cin_ogv_t));
	Com_Memset(cin->data, 0, sizeof(cin_ogv_t));

	ogg_sync_init(&g_ogm->oy);  /* Now we can read pages */

	//FIXME? can serialno be 0 in ogg? (better way to check inited?)
	//TODO: support for more than one audio stream? / detect files with one stream(or without correct ones)
	while (!g_ogm->os_audio.serialno || !g_ogm->os_video.serialno)
	{
		if (ogg_sync_pageout(&g_ogm->oy, &og) == 1)
		{
			if (strstr((char *)(og.body + 1), "vorbis"))
			{
				//FIXME? better way to find audio stream
				if (g_ogm->os_audio.serialno)
				{
					Com_Printf(S_COLOR_YELLOW "WARNING: more than one audio stream, in ogm-file(%s) ... we will stay at the first one\n", cin->name);
				}
				else
				{
					ogg_stream_init(&g_ogm->os_audio, ogg_page_serialno(&og));
					ogg_stream_pagein(&g_ogm->os_audio, &og);
				}
			}
			if (strstr((char *)(og.body + 1), "theora"))
			{
				if (g_ogm->os_video.serialno)
				{
					Com_Printf(S_COLOR_YELLOW "WARNING: more than one video stream, in ogm-file(%s) ... we will stay at the first one\n", cin->name);
				}
				else
				{
					ogg_stream_init(&g_ogm->os_video, ogg_page_serialno(&og));
					ogg_stream_pagein(&g_ogm->os_video, &og);
				}
			}
		}
		else if (OGV_LoadBlockToSync(cin))
		{
			break;
		}
	}

	if (!g_ogm->os_audio.serialno)
	{
		Com_Printf(S_COLOR_YELLOW "WARNING: Haven't found a audio(vorbis) stream in ogm-file (%s)\n", cin->name);
		return qfalse;
	}

	if (!g_ogm->os_video.serialno)
	{
		Com_Printf(S_COLOR_YELLOW "WARNING: Haven't found a video stream in ogm-file (%s)\n", cin->name);
		return qfalse;
	}

	//load vorbis header
	vorbis_info_init(&g_ogm->vi);
	vorbis_comment_init(&g_ogm->vc);
	i = 0;
	while (i < 3)
	{
		status = ogg_stream_packetout(&g_ogm->os_audio, &op);
		if (status < 0)
		{
			Com_Printf(S_COLOR_YELLOW "WARNING: Corrupt ogg packet while loading vorbis-headers, ogm-file(%s)\n", cin->name);
			return qfalse;
		}
		if (status > 0)
		{
			status = vorbis_synthesis_headerin(&g_ogm->vi, &g_ogm->vc, &op);
			if (i == 0 && status < 0)
			{
				Com_Printf(S_COLOR_YELLOW "WARNING: This Ogg bitstream does not contain Vorbis audio data, ogm-file(%s)\n", cin->name);
				return qfalse;
			}
			++i;
		}
		else if (OGV_LoadPagesToStreams(cin))
		{
			if (OGV_LoadBlockToSync(cin))
			{
				Com_Printf(S_COLOR_YELLOW "WARNING: Couldn't find all vorbis headers before end of ogm-file (%s)\n", cin->name);
				return qfalse;
			}
		}
	}

	vorbis_synthesis_init(&g_ogm->vd, &g_ogm->vi);

	// Do init
	{
		theora_info_init(&g_ogm->th_info);
		theora_comment_init(&g_ogm->th_comment);

		i = 0;
		while (i < 3)
		{
			status = ogg_stream_packetout(&g_ogm->os_video, &op);
			if (status < 0)
			{
				Com_Printf(S_COLOR_YELLOW "WARNING: Corrupt ogg packet while loading theora-headers, ogm-file(%s)\n", cin->name);
				return qfalse;
			}
			else if (status > 0)
			{
				status = theora_decode_header(&g_ogm->th_info, &g_ogm->th_comment, &op);
				if (i == 0 && status != 0)
				{
					Com_Printf(S_COLOR_YELLOW "WARNING: This Ogg bitstream does not contain theora data, ogm-file(%s)\n", cin->name);
					return qfalse;
				}
				++i;
			}
			else if (OGV_LoadPagesToStreams(cin))
			{
				if (OGV_LoadBlockToSync(cin))
				{
					Com_Printf(S_COLOR_YELLOW "WARNING: Couldn't find all theora headers before end of ogm-file (%s)\n", cin->name);
					return qfalse;
				}
			}
		}

		theora_decode_init(&g_ogm->th_state, &g_ogm->th_info);

		g_ogm->Vtime_unit = ((ogg_int64_t) g_ogm->th_info.fps_denominator * 1000 * 10000 / g_ogm->th_info.fps_numerator);
	}

	Com_DPrintf("Theora init done (%s)\n", cin->name);
	return qtrue;
}
Exemple #21
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);
}
Exemple #22
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 = 0;
		th_decode_ctl(td, TH_DECCTL_SET_PPLEVEL, &pp_level, sizeof(pp_level));
		pp_inc = 0;

		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_RGBA8, 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;
};
Exemple #23
0
 int main(){
  ogg_sync_state   oy; /* sync and verify incoming physical bitstream */
  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 bitstream user comments */
  vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
  vorbis_block     vb; /* local working space for packet->PCM decode */

  char *buffer;
  int  bytes;

  FILE *instream;
  FILE *outstream;
  char *inname = "01.ogg";
  char *outname = "esmith2000-09-28d1t15.raw";

//#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
//  /* 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

#if defined(macintosh) && defined(__MWERKS__)
  {
    int argc;
    char **argv;
    argc=ccommand(&argv); /* get a "command line" from the Mac user */
                     /* this also lets the user set stdin and stdout */
  }
#endif

  /********** Decode setup ************/

  //opening the file
  
  
  if( fopen_s( &instream, inname, "rb" ) != 0 )
  {
	  fprintf(stderr,"Can not open file %s\n", inname);
      exit(1);
  };
  
  if( fopen_s( &outstream, outname, "wb" ) != 0 )
  {
	  fprintf(stderr,"Can not open file %s\n", outname);
      exit(1);
  }


  ogg_sync_init(&oy); /* Now we can read pages */
  
  while(1){ /* we repeat if the bitstream is chained */
    int eos=0;
    int i;

    /* 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. */

    /* submit a 4k block to libvorbis' Ogg layer */
    buffer=ogg_sync_buffer(&oy,4096);
    //bytes=fread(buffer,1,4096,stdin);
	bytes=fread(buffer,1,4096,instream);
    ogg_sync_wrote(&oy,bytes);
    
    /* Get the first page. */
    if(ogg_sync_pageout(&oy,&og)!=1){
      /* have we simply run out of data?  If so, we're done. */
      if(bytes<4096)break;
      
      /* error case.  Must not be Vorbis data */
      fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n");
      exit(1);
    }
  
    /* Get the serial number and set up the rest of decode. */
    /* serialno first; use it to set up a logical stream */
    ogg_stream_init(&os,ogg_page_serialno(&og));
    
    /* 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(&vi);
    vorbis_comment_init(&vc);
    if(ogg_stream_pagein(&os,&og)<0){ 
      /* error; stream version mismatch perhaps */
      fprintf(stderr,"Error reading first page of Ogg bitstream data.\n");
      exit(1);
    }
    
    if(ogg_stream_packetout(&os,&op)!=1){ 
      /* no page? must not be vorbis */
      fprintf(stderr,"Error reading initial header packet.\n");
      exit(1);
    }
    
    if(vorbis_synthesis_headerin(&vi,&vc,&op)<0){ 
      /* error case; not a vorbis header */
      fprintf(stderr,"This Ogg bitstream does not contain Vorbis "
              "audio data.\n");
      exit(1);
    }
    
    /* 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 read
       and submit data until we get our two packets, 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;
    while(i<2){
      while(i<2){
        int result=ogg_sync_pageout(&oy,&og);
        if(result==0)break; /* Need more data */
        /* Don't complain about missing or corrupt data yet. We'll
           catch it at the packet output phase */
        if(result==1){
          ogg_stream_pagein(&os,&og); /* we can ignore any errors here
                                         as they'll also become apparent
                                         at packetout */
          while(i<2){
            result=ogg_stream_packetout(&os,&op);
            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. */
              fprintf(stderr,"Corrupt secondary header.  Exiting.\n");
              exit(1);
            }
            result=vorbis_synthesis_headerin(&vi,&vc,&op);
            if(result<0){
              fprintf(stderr,"Corrupt secondary header.  Exiting.\n");
              exit(1);
            }
            i++;
          }
        }
      }
      /* no harm in not checking before adding more */
      buffer=ogg_sync_buffer(&oy,4096);
      //bytes=fread(buffer,1,4096,stdin);
	  bytes=fread(buffer,1,4096,instream);
      if(bytes==0 && i<2){
        fprintf(stderr,"End of file before finding all Vorbis headers!\n");
        exit(1);
      }
      ogg_sync_wrote(&oy,bytes);
    }
    
    /* Throw the comments plus a few lines about the bitstream we're
       decoding */
    {
      char **ptr=vc.user_comments;
      while(*ptr){
        fprintf(stderr,"%s\n",*ptr);
        ++ptr;
      }
      fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi.channels,vi.rate);
      fprintf(stderr,"Encoded by: %s\n\n",vc.vendor);
    }
    
    convsize=4096/vi.channels;

    /* OK, got and parsed all three headers. Initialize the Vorbis
       packet->PCM decoder. */
    if(vorbis_synthesis_init(&vd,&vi)==0){ /* central decode state */
      vorbis_block_init(&vd,&vb);          /* 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 */
      
      /* The rest is just a straight decode loop until end of stream */
      while(!eos){
        while(!eos){
          int result=ogg_sync_pageout(&oy,&og);
          if(result==0)break; /* need more data */
          if(result<0){ /* missing or corrupt data at this page position */
            fprintf(stderr,"Corrupt or missing data in bitstream; "
                    "continuing...\n");
          }else{
            ogg_stream_pagein(&os,&og); /* can safely ignore errors at
                                           this point */
            while(1){
              result=ogg_stream_packetout(&os,&op);
              
              if(result==0)break; /* need more data */
              if(result<0){ /* missing or corrupt data at this page position */
                /* no reason to complain; already complained above */
              }else{
                /* we have a packet.  Decode it */
                float **pcm;
                int samples;
                
                if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
                  vorbis_synthesis_blockin(&vd,&vb);
                /* 
                   
                **pcm is a multichannel float vector.  In stereo, for
                example, pcm[0] is left, and pcm[1] is right.  samples is
                the size of each channel.  Convert the float values
                (-1.<=range<=1.) to whatever PCM format and write it out */
                
                while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0){
                  int j;
                  int clipflag=0;
                  int bout=(samples<convsize?samples:convsize);
                  
                  /* convert floats to 16 bit signed ints (host order) and
                     interleave */
                  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=floor(mono[j]*32767.f+.5f);
#else /* optional dither */
                      int val=mono[j]*32767.f+drand48()-0.5f;
#endif
                      /* might as well guard against clipping */
                      if(val>32767){
                        val=32767;
                        clipflag=1;
                      }
                      if(val<-32768){
                        val=-32768;
                        clipflag=1;
                      }
                      *ptr=val;
                      ptr+=vi.channels;
                    }
                  }
                  
                  if(clipflag)
                    fprintf(stderr,"Clipping in frame %ld\n",(long)(vd.sequence));
                  
                  
                  //fwrite(convbuffer,2*vi.channels,bout,stdout);
				  fwrite(convbuffer,2*vi.channels,bout,outstream);
                  
                  vorbis_synthesis_read(&vd,bout); /* tell libvorbis how
                                                      many samples we
                                                      actually consumed */
                }            
              }
            }
            if(ogg_page_eos(&og))eos=1;
          }
        }
        if(!eos){
          buffer=ogg_sync_buffer(&oy,4096);
          //bytes=fread(buffer,1,4096,stdin);
		  bytes=fread(buffer,1,4096,instream);
          ogg_sync_wrote(&oy,bytes);
          if(bytes==0)eos=1;
        }
      }
      
      /* ogg_page and ogg_packet structs always point to storage in
         libvorbis.  They're never freed or manipulated directly */
      
      vorbis_block_clear(&vb);
      vorbis_dsp_clear(&vd);
    }else{
      fprintf(stderr,"Error: Corrupt header during playback initialization.\n");
    }

    /* clean up this logical bitstream; before exit we see if we're
       followed by another [chained] */
    
    ogg_stream_clear(&os);
    vorbis_comment_clear(&vc);
    vorbis_info_clear(&vi);  /* must be called last */
  }

  /* OK, clean up the framer */
  ogg_sync_clear(&oy);
  
  fprintf(stderr,"Done.\n");
  return(0);
}
Exemple #24
0
static gint vorbis_open(void)
{
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_init(NULL);

    vorbis_info_init(&vi);
    vorbis_comment_init(&vc);

    if (tuple)
    {
        gchar tmpstr[32];
        gint scrint;

        add_string_from_tuple (& vc, "title", tuple, FIELD_TITLE);
        add_string_from_tuple (& vc, "artist", tuple, FIELD_ARTIST);
        add_string_from_tuple (& vc, "album", tuple, FIELD_ALBUM);
        add_string_from_tuple (& vc, "genre", tuple, FIELD_GENRE);
        add_string_from_tuple (& vc, "date", tuple, FIELD_DATE);
        add_string_from_tuple (& vc, "comment", tuple, FIELD_COMMENT);

        if ((scrint = tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL)))
        {
            g_snprintf(tmpstr, sizeof(tmpstr), "%d", scrint);
            vorbis_comment_add_tag(&vc, "tracknumber", tmpstr);
        }

        if ((scrint = tuple_get_int(tuple, FIELD_YEAR, NULL)))
        {
            g_snprintf(tmpstr, sizeof(tmpstr), "%d", scrint);
            vorbis_comment_add_tag(&vc, "year", tmpstr);
        }
    }

    if (vorbis_encode_init_vbr (& vi, input.channels, input.frequency,
     v_base_quality))
    {
        vorbis_info_clear(&vi);
        return 0;
    }

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

    srand(time(NULL));
    ogg_stream_init(&os, rand());

    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);

    while (ogg_stream_flush (& os, & og))
    {
        write_output(og.header, og.header_len);
        write_output(og.body, og.body_len);
    }

    return 1;
}
Exemple #25
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;

#if defined(macintosh) && defined(__MWERKS__)
  int argc = 0;
  char **argv = NULL;
  argc = ccommand(&argv); /* get a "command line" from the Mac user */
                          /* this also lets the user set stdin and stdout */
#endif

  /* we cheat on the WAV header; we just bypass 44 bytes and never
     verify that it matches 16bit/stereo/44.1kHz.  This is just an
     example, after all. */

#ifdef _WIN32 /* 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


  /* we cheat on the WAV header; we just bypass the header and never
     verify that it matches 16bit/stereo/44.1kHz.  This is just an
     example, after all. */

  readbuffer[0] = '\0';
  for (i=0, founddata=0; i<30 && ! feof(stdin) && ! ferror(stdin); i++)
  {
    fread(readbuffer,1,2,stdin);

    if ( ! strncmp((char*)readbuffer, "da", 2) )
    {
      founddata = 1;
      fread(readbuffer,1,6,stdin);
      break;
    }
  }

  /********** 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,0.1);

  /* 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,stdout);
		fwrite(og.body,1,og.body_len,stdout);
	}

  }
  
  while(!eos){
    long i;
    long bytes=fread(readbuffer,1,READ*4,stdin); /* stereo hardwired here */

    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++){
	buffer[0][i]=((readbuffer[i*4+1]<<8)|
		      (0x00ff&(int)readbuffer[i*4]))/32768.f;
	buffer[1][i]=((readbuffer[i*4+3]<<8)|
		      (0x00ff&(int)readbuffer[i*4+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;
	  fwrite(og.header,1,og.header_len,stdout);
	  fwrite(og.body,1,og.body_len,stdout);
	  
	  /* 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);
}
Exemple #26
0
/*****************************************************************************
 * OpenEncoder: probe the encoder and return score
 *****************************************************************************/
static int OpenEncoder( vlc_object_t *p_this )
{
    encoder_t *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys;
    int i_quality, i_min_bitrate, i_max_bitrate;
    ogg_packet header[3];

    if( p_enc->fmt_out.i_codec != VLC_CODEC_VORBIS &&
            !p_enc->b_force )
    {
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
        return VLC_ENOMEM;
    p_enc->p_sys = p_sys;

    p_enc->pf_encode_audio = Encode;
    p_enc->fmt_in.i_codec  = VLC_CODEC_FL32;
    p_enc->fmt_out.i_codec = VLC_CODEC_VORBIS;

    config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );

    i_quality = var_GetInteger( p_enc, ENC_CFG_PREFIX "quality" );
    if( i_quality > 10 ) i_quality = 10;
    if( i_quality < 0 ) i_quality = 0;

    if( var_GetBool( p_enc, ENC_CFG_PREFIX "cbr" ) ) i_quality = 0;
    i_max_bitrate = var_GetInteger( p_enc, ENC_CFG_PREFIX "max-bitrate" );
    i_min_bitrate = var_GetInteger( p_enc, ENC_CFG_PREFIX "min-bitrate" );

    /* Initialize vorbis encoder */
    vorbis_info_init( &p_sys->vi );

    if( i_quality > 0 )
    {
        /* VBR mode */
        if( vorbis_encode_setup_vbr( &p_sys->vi,
                                     p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate,
                                     i_quality * 0.1 ) )
        {
            vorbis_info_clear( &p_sys->vi );
            free( p_enc->p_sys );
            msg_Err( p_enc, "VBR mode initialisation failed" );
            return VLC_EGENERIC;
        }

        /* Do we have optional hard quality restrictions? */
        if( i_max_bitrate > 0 || i_min_bitrate > 0 )
        {
            struct ovectl_ratemanage_arg ai;
            vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_GET, &ai );

            ai.bitrate_hard_min = i_min_bitrate;
            ai.bitrate_hard_max = i_max_bitrate;
            ai.management_active = 1;

            vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_SET, &ai );

        }
        else
        {
            /* Turn off management entirely */
            vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_SET, NULL );
        }
    }
    else
    {
        if( vorbis_encode_setup_managed( &p_sys->vi,
                                         p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.audio.i_rate,
                                         i_min_bitrate > 0 ? i_min_bitrate * 1000: -1,
                                         p_enc->fmt_out.i_bitrate,
                                         i_max_bitrate > 0 ? i_max_bitrate * 1000: -1 ) )
        {
            vorbis_info_clear( &p_sys->vi );
            msg_Err( p_enc, "CBR mode initialisation failed" );
            free( p_enc->p_sys );
            return VLC_EGENERIC;
        }
    }

    vorbis_encode_setup_init( &p_sys->vi );

    /* Add a comment */
    vorbis_comment_init( &p_sys->vc);
    vorbis_comment_add_tag( &p_sys->vc, "ENCODER", "VLC media player");

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

    /* Create and store headers */
    vorbis_analysis_headerout( &p_sys->vd, &p_sys->vc,
                               &header[0], &header[1], &header[2]);
    for( int i = 0; i < 3; i++ )
    {
        if( xiph_AppendHeaders( &p_enc->fmt_out.i_extra, &p_enc->fmt_out.p_extra,
                                header[i].bytes, header[i].packet ) )
        {
            p_enc->fmt_out.i_extra = 0;
            p_enc->fmt_out.p_extra = NULL;
        }
    }

    p_sys->i_channels = p_enc->fmt_in.audio.i_channels;
    p_sys->i_last_block_size = 0;
    p_sys->i_samples_delay = 0;

    ConfigureChannelOrder(p_sys->pi_chan_table, p_sys->vi.channels,
                          p_enc->fmt_in.audio.i_physical_channels, true);

    return VLC_SUCCESS;
}
Exemple #27
0
int input_calculate_ogg_sleep(ogg_page *page)
{
    static ogg_stream_state os;
    ogg_packet op;
    static vorbis_info vi;
    static vorbis_comment vc;
    static input_type codec = ICES_INPUT_UNKNOWN;
    static int need_start_pos, need_headers, state_in_use = 0;
    static int serialno = 0;
    static uint64_t offset;
    static uint64_t first_granulepos;

    if (ogg_page_granulepos(page) == -1)
    {
        LOG_ERROR0("Timing control: corrupt timing information in vorbis file, cannot stream.");
        return -1;
    }
    if (ogg_page_bos (page))
    {
        control.oldsamples = 0;

        if (state_in_use)
            ogg_stream_clear (&os);
        ogg_stream_init (&os, ogg_page_serialno (page));
        serialno = ogg_page_serialno (page);
        state_in_use = 1;
        vorbis_info_init (&vi);
        vorbis_comment_init (&vc);
        need_start_pos = 1;
        need_headers = 3;
        codec = ICES_INPUT_UNKNOWN;
        offset = (uint64_t)0;
    }
    if (need_start_pos)
    {
        int found_first_granulepos = 0;

        ogg_stream_pagein (&os, page);
        while (ogg_stream_packetout (&os, &op) == 1)
        {
            if (need_headers)
            {
                /* check for Vorbis. For Vorbis the Magic is {0x01|0x03|0x05}"vorbis" */
                if (op.bytes > 7 && memcmp(op.packet+1, "vorbis", 6) == 0)
                {
                    if (vorbis_synthesis_headerin (&vi, &vc, &op) < 0)
                    {
                        LOG_ERROR0("Timing control: can't determine sample rate for input, not vorbis.");
                        control.samplerate = 0;
                        vorbis_info_clear (&vi);
                        ogg_stream_clear (&os);
                        return -1;
                    }
                    control.samplerate = vi.rate;
                    codec = ICES_INPUT_VORBIS;
                }
                /* check for Opus. For Opus the magic is "OpusHead" */
                else if (op.bytes == 19 && memcmp(op.packet, "OpusHead", 8) == 0)
                {
                    if (op.packet[8] != 1)
                    {
                        LOG_ERROR0("Timing control: can't determine sample rate for input, unsupported Opus version.");
                        control.samplerate = 0;
                        vorbis_info_clear (&vi);
                        ogg_stream_clear (&os);
                        return -1;
                    }
                    /* Sample rate is fixed for Opus: 48kHz */
                    control.samplerate = 48000;
                    codec = ICES_INPUT_OGG;
                    /* No more headers after this one needed */
                    need_headers = 1;
                }
                else if (op.bytes >= 80 && memcmp(op.packet, "Speex   ", 8) == 0)
                {
                    if (__read_int32_le(op.packet+28) != 1 || __read_int32_le(op.packet+32) != op.bytes)
                    {
                        LOG_ERROR0("Timing control: can't determine sample rate for input, bad or unsupported Speex header.");
                        control.samplerate = 0;
                        vorbis_info_clear (&vi);
                        ogg_stream_clear (&os);
                        return -1;
                    }

                    control.samplerate = __read_int32_le(op.packet+36);
                    codec = ICES_INPUT_OGG;
                    /* No more headers after this one needed */
                    need_headers = 1;
                }
                else if (op.bytes >= 51 && memcmp(op.packet, "\177FLAC\1\0", 7) == 0 && memcmp(op.packet+9, "fLaC\0", 5) == 0)
                {
                    control.samplerate = __read_int20_be(op.packet+27);
                    codec = ICES_INPUT_OGG;
                    /* No more headers after this one needed */
                    need_headers = 1;
                }
                else if (codec == ICES_INPUT_UNKNOWN)
                {
                    LOG_ERROR0("Timing control: can't determine sample rate for input, unsupported input format.");
                    control.samplerate = 0;
                    vorbis_info_clear (&vi);
                    ogg_stream_clear (&os);
                    return -1;
                }
                need_headers--;

                if (need_headers == 0)
                {
                    vorbis_comment_clear (&vc);
                    first_granulepos = (uint64_t)0;
                    return 0;
                }
                continue;
            }
            /* headers have been read */
            if (first_granulepos == 0 && op.granulepos > 0)
            {
                first_granulepos = op.granulepos;
                found_first_granulepos = 1;
            }
            if (codec == ICES_INPUT_VORBIS)
            {
                offset += vorbis_packet_blocksize (&vi, &op) / 4;
            }
        }
        if (!found_first_granulepos)
            return 0;

        need_start_pos = 0;
        control.oldsamples = first_granulepos - offset;
        vorbis_info_clear (&vi);
        ogg_stream_clear (&os);
        state_in_use = 0;
    }
    if (serialno != ogg_page_serialno (page))
    {
        LOG_ERROR0 ("Found page which does not belong to current logical stream");
        return -1;
    }
    control.samples = ogg_page_granulepos (page) - control.oldsamples;
    control.oldsamples = ogg_page_granulepos (page);

    control.senttime += ((uint64_t)control.samples * 1000000 /
            (uint64_t)control.samplerate);

    return 0;
}
Exemple #28
0
int lame_encode_ogg_init(lame_global_flags *gfp)
{
  lame_internal_flags *gfc=gfp->internal_flags;
  char comment[MAX_COMMENT_LENGTH+1];

  
  /********** Encode setup ************/
  
  /* choose an encoding mode */
  /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
  if (gfp->compression_ratio < 5.01) {
    memcpy(&vi2,&info_E,sizeof(vi2));
    MSGF( gfc, "Encoding with Vorbis mode info_E \n" );
  } else if (gfp->compression_ratio < 6) {
    memcpy(&vi2,&info_D,sizeof(vi2));
    MSGF( gfc, "Encoding with Vorbis mode info_D \n" );
  } else if (gfp->compression_ratio < 8) {
    memcpy(&vi2,&info_C,sizeof(vi2));
    MSGF( gfc, "Encoding with Vorbis mode info_C \n" );
  } else if (gfp->compression_ratio < 10) {
    memcpy(&vi2,&info_B,sizeof(vi2));
    MSGF( gfc, "Encoding with Vorbis mode info_B \n" );
  } else if (gfp->compression_ratio < 12) {
    memcpy(&vi2,&info_A,sizeof(vi2));
    MSGF( gfc, "Encoding with Vorbis mode info_A \n" );
  } else {
    memcpy(&vi2,&info_A,sizeof(vi2));
    MSGF( gfc, "Encoding with Vorbis mode info_A \n" );
  }

  vi2.channels = gfc->channels_out;
  vi2.rate = gfp->out_samplerate;

  
  /* add a comment */
  vorbis_comment_init(&vc2);
  vorbis_comment_add(&vc2,"Track encoded using L.A.M.E. libvorbis interface.");

  /* Add ID3-style comments to the output using (for the time being) the
     "private data members" in the "id3tag_spec" data structure. This was
     from a patch by Ralph Giles <*****@*****.**> */
     
#ifdef THIS_CODE_IS_NOT_BROKEN_ANYMORE     
  if(gfp->tag_spec.title) {
    strcpy(comment,"TITLE=");
    strncat(comment,gfp->tag_spec.title,MAX_COMMENT_LENGTH-strlen(comment));
    vorbis_comment_add(&vc2,comment);
  }
  if(gfp->tag_spec.artist) {
    strcpy(comment,"ARTIST=");
    strncat(comment,gfp->tag_spec.artist,MAX_COMMENT_LENGTH-strlen(comment));
    vorbis_comment_add(&vc2,comment);
  }
  if(gfp->tag_spec.album) {
    strcpy(comment,"ALBUM=");
    strncat(comment,gfp->tag_spec.album,MAX_COMMENT_LENGTH-strlen(comment));
    vorbis_comment_add(&vc2,comment);
  }
  /* pretend that the ID3 fields are equivalent to the Vorbis fields */
  if(gfp->tag_spec.year) {
    sprintf(comment, "DATE=%d", gfp->tag_spec.year);
    vorbis_comment_add(&vc2,comment);
  }
  if(gfp->tag_spec.comment) {
    strcpy(comment,"DESCRIPTION=");
    strncat(comment,gfp->tag_spec.comment,MAX_COMMENT_LENGTH-strlen(comment));
    vorbis_comment_add(&vc2,comment);
  }
  /* TODO -- support for track and genre */
#endif  

  /* set up the analysis state and auxiliary encoding storage */
  vorbis_analysis_init(&vd2,&vi2);
  vorbis_block_init(&vd2,&vb2);
  
  /* 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(&os2,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(&vd2,&vc2,&header,&header_comm,&header_code);
    ogg_stream_packetin(&os2,&header); /* automatically placed in its own
					 page */
    ogg_stream_packetin(&os2,&header_comm);
    ogg_stream_packetin(&os2,&header_code);
    
    /* no need to write out here.  We'll get to that in the main loop */
  }
  
  return 0;
}
Exemple #29
0
int OggInit(CFile *f, OggData *data)
{
	ogg_packet packet;
	int num_vorbis;
#ifdef USE_THEORA
	int num_theora;
#endif
	int stream_start;
	int ret;

	unsigned magic;
	f->read(&magic, sizeof(magic));
	if (SDL_SwapLE32(magic) != 0x5367674F) { // "OggS" in ASCII
		return -1;
	}
	f->seek(0, SEEK_SET);

	ogg_sync_init(&data->sync);

	vorbis_info_init(&data->vinfo);
	vorbis_comment_init(&data->vcomment);

#ifdef USE_THEORA
	theora_info_init(&data->tinfo);
	theora_comment_init(&data->tcomment);
#endif

#ifdef USE_THEORA
	num_theora = 0;
#endif
	num_vorbis = 0;
	stream_start = 0;
	while (!stream_start) {
		ogg_stream_state test;

		if (OggGetNextPage(&data->page, &data->sync, f)) {
			return -1;
		}

		if (!ogg_page_bos(&data->page)) {
			if (num_vorbis) {
				ogg_stream_pagein(&data->astream, &data->page);
			}
#ifdef USE_THEORA
			if (num_theora) {
				ogg_stream_pagein(&data->vstream, &data->page);
			}
#endif
			stream_start = 1;
			break;
		}

		ogg_stream_init(&test, ogg_page_serialno(&data->page));
		ogg_stream_pagein(&test, &data->page);

		// initial codec headers
		while (ogg_stream_packetout(&test, &packet) == 1) {
#ifdef USE_THEORA
			if (theora_decode_header(&data->tinfo, &data->tcomment, &packet) >= 0) {
				memcpy(&data->vstream, &test, sizeof(test));
				++num_theora;
			} else
#endif
			if (!vorbis_synthesis_headerin(&data->vinfo, &data->vcomment, &packet)) {
				memcpy(&data->astream, &test, sizeof(test));
				++num_vorbis;
			} else {
				ogg_stream_clear(&test);
			}
		}
	}

	data->audio = num_vorbis;
#ifdef USE_THEORA
	data->video = num_theora;
#endif

	// remainint codec headers
	while ((num_vorbis && num_vorbis < 3)
#ifdef USE_THEORA
	  || (num_theora && num_theora < 3) ) {
		// are we in the theora page ?
		while (num_theora && num_theora < 3 &&
		  (ret = ogg_stream_packetout(&data->vstream, &packet))) {
			if (ret < 0) {
				return -1;
			}
			if (theora_decode_header(&data->tinfo, &data->tcomment, &packet)) {
				return -1;
			}
			++num_theora;
		}
#else
	  ) {
#endif

		// are we in the vorbis page ?
		while (num_vorbis && num_vorbis < 3 && 
		  (ret = ogg_stream_packetout(&data->astream, &packet))) {
			if (ret < 0) {
				return -1;
			}
			if (vorbis_synthesis_headerin(&data->vinfo, &data->vcomment, &packet)) {
				return -1;
				
			}
			++num_vorbis;
		}

		if (OggGetNextPage(&data->page, &data->sync, f)) {
				break;
		}

		if (num_vorbis) {
			ogg_stream_pagein(&data->astream, &data->page);
		}
#ifdef USE_THEORA
		if (num_theora) {
			ogg_stream_pagein(&data->vstream, &data->page);
		}
#endif
	}

	if (num_vorbis) {
		vorbis_synthesis_init(&data->vdsp, &data->vinfo);
		vorbis_block_init(&data->vdsp, &data->vblock);
	} else {
    	vorbis_info_clear(&data->vinfo);
    	vorbis_comment_clear(&data->vcomment);
	}

#ifdef USE_THEORA
	if (num_theora) {
		theora_decode_init(&data->tstate, &data->tinfo);
		data->tstate.internal_encode = NULL;  // needed for a bug in libtheora (fixed in next release)
	} else {
    	theora_info_clear(&data->tinfo);
    	theora_comment_clear(&data->tcomment);
	}

	return !(num_vorbis || num_theora);
#else
	return !num_vorbis;
#endif
}
Exemple #30
0
int lame_decode_ogg_initfile( lame_global_flags*  gfp,
                              FILE*               fd,
                              mp3data_struct*     mp3data )
{

  lame_internal_flags *gfc = gfp->internal_flags;
  char *buffer;
  int  bytes;
  int i;


  /********** Decode setup ************/

  ogg_sync_init(&oy); /* Now we can read pages */
  

  /* 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. */
  
  /* submit a 4k block to libvorbis' Ogg layer */
  buffer=ogg_sync_buffer(&oy,4096);
  bytes=fread(buffer,1,4096,fd);
  ogg_sync_wrote(&oy,bytes);
  
  /* Get the first page. */
  if(ogg_sync_pageout(&oy,&og)!=1){
    /* error case.  Must not be Vorbis data */
    ERRORF( gfc, "Error initializing Ogg bitstream data.\n" );
    return -1;
  }
  
  /* Get the serial number and set up the rest of decode. */
  /* serialno first; use it to set up a logical stream */
  ogg_stream_init(&os,ogg_page_serialno(&og));
  
  /* 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(&vi);
  vorbis_comment_init(&vc);
  if(ogg_stream_pagein(&os,&og)<0){ 
    /* error; stream version mismatch perhaps */
    ERRORF( gfc, "Error reading first page of Ogg bitstream data.\n" );
    return -1;
  }
  
  if(ogg_stream_packetout(&os,&op)!=1){ 
    /* no page? must not be vorbis */
    ERRORF( gfc, "Error reading initial header packet.\n" );
    return -1;
  }
  
  if(vorbis_synthesis_headerin(&vi,&vc,&op)<0){ 
    /* error case; not a vorbis header */
    ERRORF( gfc, "This Ogg bitstream does not contain Vorbis "
	    "audio data.\n");
    return -1;
  }
  
  /* 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;
  while(i<2){
    while(i<2){
      int result=ogg_sync_pageout(&oy,&og);
      if(result==0)break; /* Need more data */
      /* Don't complain about missing or corrupt data yet.  We'll
	 catch it at the packet output phase */
      if(result==1){
	ogg_stream_pagein(&os,&og); /* we can ignore any errors here
				       as they'll also become apparent
				       at packetout */
	while(i<2){
	  result=ogg_stream_packetout(&os,&op);
	  if(result==0)break;
	  if(result==-1){
	    /* Uh oh; data at some point was corrupted or missing!
	       We can't tolerate that in a header.  Die. */
	    ERRORF( gfc, "Corrupt secondary header.  Exiting.\n" );
	    return -1;
	  }
	  vorbis_synthesis_headerin(&vi,&vc,&op);
	  i++;
	}
      }
    }
    /* no harm in not checking before adding more */
    buffer=ogg_sync_buffer(&oy,4096);
    bytes=fread(buffer,1,4096,fd);
    if(bytes==0 && i<2){
      ERRORF( gfc, "End of file before finding all Vorbis headers!\n" );
      return -1;
    }
    ogg_sync_wrote(&oy,bytes);
  }
  
  /* Throw the comments plus a few lines about the bitstream we're
     decoding */
  {
    /*
    char **ptr=vc.user_comments;
    while(*ptr){
      MSGF( gfc, "%s\n", *ptr );
      ++ptr;
    }
    MSGF( gfc, "\nBitstream is %d channel, %ldHz\n", vi.channels, vi.rate );
    MSGF( gfc, "Encoded by: %s\n\n", vc.vendor );
    */
  }
  
  
  /* OK, got and parsed all three headers. Initialize the Vorbis
     packet->PCM decoder. */
  vorbis_synthesis_init(&vd,&vi); /* central decode state */
  vorbis_block_init(&vd,&vb);     /* 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 */
  
  mp3data->stereo = vi.channels;
  mp3data->samplerate = vi.rate;
  mp3data->bitrate = 0; //ov_bitrate_instant(&vf);
  mp3data->nsamp=MAX_U_32_NUM;
  
  return 0;
}