示例#1
0
static gboolean
gst_ogg_avi_parse_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
  GstOggAviParse *ogg;
  gboolean ret;

  ogg = GST_OGG_AVI_PARSE (parent);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;

      gst_event_parse_caps (event, &caps);
      ret = gst_ogg_avi_parse_setcaps (pad, caps);
      gst_event_unref (event);
      break;
    }
    case GST_EVENT_FLUSH_START:
      ret = gst_pad_push_event (ogg->srcpad, event);
      break;
    case GST_EVENT_FLUSH_STOP:
      ogg_sync_reset (&ogg->sync);
      ogg_stream_reset (&ogg->stream);
      ogg->discont = TRUE;
      ret = gst_pad_push_event (ogg->srcpad, event);
      break;
    default:
      ret = gst_pad_push_event (ogg->srcpad, event);
      break;
  }
  return ret;
}
示例#2
0
void FLAC__ogg_decoder_aspect_flush(FLAC__OggDecoderAspect *aspect)
{
    (void)ogg_stream_reset(&aspect->stream_state);
    (void)ogg_sync_reset(&aspect->sync_state);
    aspect->end_of_stream = false;
    aspect->have_working_page = false;
}
示例#3
0
static PyObject * py_ogg_ogg_sync_reset(PyObject *self, PyObject *args) {
  int c_out;
  int size;
  ogg_sync_state * oy;
  PyArg_ParseTuple(args, "s#", &oy, &size);
  c_out = ogg_sync_reset(oy);
  return Py_BuildValue("i", c_out);
};
示例#4
0
文件: framing.c 项目: Erikhht/TCPMP
int ogg_sync_destroy(ogg_sync_state *oy){
  if(oy){
    ogg_sync_reset(oy);
    ogg_buffer_destroy(oy->bufferpool);
    memset(oy,0,sizeof(*oy));
    _ogg_free(oy);
  }
  return OGG_SUCCESS;
}
示例#5
0
/* save a tiny smidge of verbosity to make the code more readable */
static void _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
  if(vf->datasource){ 
    (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET);
    vf->offset=offset;
    ogg_sync_reset(vf->oy);
  }else{
    /* shouldn't happen unless someone writes a broken callback */
    return;
  }
}
/*
 * Class:     org_tritonus_lowlevel_ogg_SyncState
 * Method:    reset
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_org_tritonus_lowlevel_ogg_SyncState_reset
(JNIEnv* env, jobject obj)
{
	ogg_sync_state*	handle;

	if (debug_flag) { fprintf(debug_file, "Java_org_tritonus_lowlevel_ogg_SyncState_reset(): begin\n"); }
	handle = getHandle(env, obj);
	ogg_sync_reset(handle);
	if (debug_flag) { fprintf(debug_file, "Java_org_tritonus_lowlevel_ogg_SyncState_reset(): end\n"); }
}
示例#7
0
static void seek_byte( demux_t *p_demux, int64_t i_pos )
{
    demux_sys_t *p_sys  = p_demux->p_sys;

    if ( ! stream_Seek( p_demux->s, i_pos ) )
    {
        ogg_sync_reset( &p_sys->oy );

        p_sys->i_input_position = i_pos;
        p_sys->b_page_waiting = false;
    }
}
示例#8
0
文件: speex.c 项目: gitkaste/moc
static int count_time (struct spx_data *data)
{
	unsigned long last_granulepos = 0;

	/* Seek to somewhere neer the last page */
	if (io_file_size(data->stream) > 10000) {
		debug ("Seeking near the end");
		if (io_seek(data->stream, -10000, SEEK_END) == -1)
			logit ("Seeking failed, scaning whole file");
		ogg_sync_reset (&data->oy);
	}
	
	/* Read granulepos from the last packet */
	while (!io_eof(data->stream)) {

		/* Sync to page and read it */
		while (!io_eof(data->stream)) {
			char *buf;
			int nb_read;

			if (ogg_sync_pageout(&data->oy, &data->og) == 1) {
				debug ("Sync");
				break;
			}
			else if (!io_eof(data->stream)) {
				debug ("Need more data");
				buf = ogg_sync_buffer (&data->oy, 200);
				nb_read = io_read (data->stream, buf, 200);
				ogg_sync_wrote (&data->oy, nb_read);
			}
		}

		/* We have last packet */
		if (io_eof(data->stream))
			break;

		last_granulepos = ogg_page_granulepos (&data->og);
	}

	return last_granulepos / data->rate;
}
示例#9
0
static GstStateChangeReturn
gst_ogg_avi_parse_change_state (GstElement * element, GstStateChange transition)
{
  GstOggAviParse *ogg;
  GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE;

  ogg = GST_OGG_AVI_PARSE (element);

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      ogg_sync_init (&ogg->sync);
      break;
    case GST_STATE_CHANGE_READY_TO_PAUSED:
      ogg_sync_reset (&ogg->sync);
      ogg_stream_reset (&ogg->stream);
      ogg->serial = -1;
      ogg->discont = TRUE;
      break;
    case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
      break;
    default:
      break;
  }

  result = parent_class->change_state (element, transition);

  switch (transition) {
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
      break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      break;
    case GST_STATE_CHANGE_READY_TO_NULL:
      ogg_sync_clear (&ogg->sync);
      break;
    default:
      break;
  }
  return result;
}
示例#10
0
	void VideoClip_Theora::_executeRestart()
	{
		bool paused = this->timer->isPaused();
		if (!paused)
		{
			this->timer->pause();
		}
		long initialGranule = 0;
		th_decode_ctl(this->info.TheoraDecoder, TH_DECCTL_SET_GRANPOS, &initialGranule, sizeof(initialGranule));
		th_decode_free(this->info.TheoraDecoder);
		this->info.TheoraDecoder = th_decode_alloc(&this->info.TheoraInfo, this->info.TheoraSetup);
		ogg_stream_reset(&this->info.TheoraStreamState);
		if (this->audioInterface != NULL)
		{
			// empty the DSP buffer
			ogg_packet opVorbis;
			this->readAudioSamples = 0;
			while (ogg_stream_packetout(&this->info.VorbisStreamState, &opVorbis) > 0)
			{
				if (vorbis_synthesis(&this->info.VorbisBlock, &opVorbis) == 0)
				{
					vorbis_synthesis_blockin(&this->info.VorbisDSPState, &this->info.VorbisBlock);
				}
			}
			ogg_stream_reset(&this->info.VorbisStreamState);
		}
		ogg_sync_reset(&this->info.OggSyncState);
		this->stream->seek(0);
		ogg_int64_t granulePos = 0;
		th_decode_ctl(this->info.TheoraDecoder, TH_DECCTL_SET_GRANPOS, &granulePos, sizeof(granulePos));
		this->endOfFile = false;
		this->restarted = true;
		if (!paused)
		{
			this->timer->play();
		}
	}
示例#11
0
文件: speex.c 项目: jonsafari/mocp
static int count_time (struct spx_data *data)
{
	ogg_int64_t last_granulepos = 0;

	/* Seek to somewhere near the last page */
	if (io_file_size(data->stream) > 10000) {
		debug ("Seeking near the end");
		if (io_seek(data->stream, -10000, SEEK_END) == -1)
			logit ("Seeking failed, scanning whole file");
		ogg_sync_reset (&data->oy);
	}

	/* Read granulepos from the last packet */
	while (!io_eof(data->stream)) {

		/* Sync to page and read it */
		while (!io_eof(data->stream)) {
			if (ogg_sync_pageout(&data->oy, &data->og) == 1) {
				debug ("Sync");
				break;
			}

			if (!io_eof(data->stream)) {
				debug ("Need more data");
				get_more_data (data);
			}
		}

		/* We have last packet */
		if (io_eof(data->stream))
			break;

		last_granulepos = ogg_page_granulepos (&data->og);
	}

	return last_granulepos / data->rate;
}
示例#12
0
static gboolean
gst_ogg_avi_parse_event (GstPad * pad, GstEvent * event)
{
  GstOggAviParse *ogg;
  gboolean ret;

  ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_FLUSH_START:
      ret = gst_pad_push_event (ogg->srcpad, event);
      break;
    case GST_EVENT_FLUSH_STOP:
      ogg_sync_reset (&ogg->sync);
      ogg_stream_reset (&ogg->stream);
      ogg->discont = TRUE;
      ret = gst_pad_push_event (ogg->srcpad, event);
      break;
    default:
      ret = gst_pad_push_event (ogg->srcpad, event);
      break;
  }
  return ret;
}
示例#13
0
static int
spx_read_header (SF_PRIVATE * psf)
{	static SpeexStereoState STEREO_INIT = SPEEX_STEREO_STATE_INIT ;

	OGG_PRIVATE* odata = psf->container_data ;
	SPX_PRIVATE* spx = psf->codec_data ;

	ogg_int64_t page_granule = 0 ;
	int stream_init = 0 ;
	int	page_nb_packets = 0 ;
	int packet_count = 0 ;
	int enh_enabled = 1 ;
	int force_mode = -1 ;
	char * data ;
	int nb_read ;
	int lookahead ;

printf ("%s %d\n", __func__, __LINE__) ;

	psf_log_printf (psf, "Speex header\n") ;
	odata->eos = 0 ;

	/* Reset ogg stuff which has already been used in src/ogg.c. */
	ogg_stream_reset (&odata->ostream) ;
	ogg_sync_reset (&odata->osync) ;

	/* Seek to start of stream. */
	psf_fseek (psf, 0, SEEK_SET) ;

	/* Initialize. */
	ogg_sync_init (&odata->osync) ;
	speex_bits_init (&spx->bits) ;

	/* Set defaults. */
	psf->sf.channels = -1 ;
	psf->sf.samplerate = 0 ;
	spx->stereo = STEREO_INIT ;

	/* Get a pointer to the ogg buffer and read data into it. */
	data = ogg_sync_buffer (&odata->osync, OGG_SPX_READ_SIZE) ;
	nb_read = psf_fread (data, 1, OGG_SPX_READ_SIZE, psf) ;
	ogg_sync_wrote (&odata->osync, nb_read) ;

	/* Now we chew on Ogg packets. */
	while (ogg_sync_pageout (&odata->osync, &odata->opage) == 1)
	{	if (stream_init == 0)
		{	ogg_stream_init (&odata->ostream, ogg_page_serialno (&odata->opage)) ;
			stream_init = 1 ;
			} ;

		if (ogg_page_serialno (&odata->opage) != odata->ostream.serialno)
		{	/* so all streams are read. */
			ogg_stream_reset_serialno (&odata->ostream, ogg_page_serialno (&odata->opage)) ;
			} ;

		/*Add page to the bitstream*/
		ogg_stream_pagein (&odata->ostream, &odata->opage) ;
		page_granule = ogg_page_granulepos (&odata->opage) ;
		page_nb_packets = ogg_page_packets (&odata->opage) ;

		/*Extract all available packets*/
		while (odata->eos == 0 && ogg_stream_packetout (&odata->ostream, &odata->opacket) == 1)
		{	if (odata->opacket.bytes >= 8 && memcmp (odata->opacket.packet, "Speex   ", 8) == 0)
			{	spx->serialno = odata->ostream.serialno ;
				} ;

			if (spx->serialno == -1 || odata->ostream.serialno != spx->serialno)
				break ;

			if (packet_count == 0)
			{	spx->state = spx_header_read (psf, &odata->opacket, enh_enabled, force_mode) ;
				if (! spx->state)
					break ;

				speex_decoder_ctl (spx->state, SPEEX_GET_LOOKAHEAD, &lookahead) ;
				if (spx->nframes == 0)
					spx->nframes = 1 ;
				}
			else if (packet_count == 1)
			{	spx_print_comments ((const char*) odata->opacket.packet, odata->opacket.bytes) ;
				}
			else if (packet_count < 2 + spx->header.extra_headers)
			{	/* Ignore extra headers */
				}
			packet_count ++ ;
			} ;
		} ;

	psf_log_printf (psf, "End\n") ;

	psf_log_printf (psf, "packet_count %d\n", packet_count) ;
	psf_log_printf (psf, "page_nb_packets %d\n", page_nb_packets) ;
	psf_log_printf (psf, "page_granule %lld\n", page_granule) ;

	return 0 ;
} /* spx_read_header */
示例#14
0
static GstFlowReturn
gst_ogg_avi_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
{
  GstFlowReturn result = GST_FLOW_OK;
  GstOggAviParse *ogg;
  guint size;
  gchar *oggbuf;
  gint ret = -1;

  ogg = GST_OGG_AVI_PARSE (parent);

  size = gst_buffer_get_size (buffer);

  GST_LOG_OBJECT (ogg, "Chain function received buffer of size %d", size);

  if (GST_BUFFER_IS_DISCONT (buffer)) {
    ogg_sync_reset (&ogg->sync);
    ogg->discont = TRUE;
  }

  /* write data to sync layer */
  oggbuf = ogg_sync_buffer (&ogg->sync, size);
  gst_buffer_extract (buffer, 0, oggbuf, size);
  ogg_sync_wrote (&ogg->sync, size);
  gst_buffer_unref (buffer);

  /* try to get as many packets out of the stream as possible */
  do {
    ogg_page page;

    /* try to swap out a page */
    ret = ogg_sync_pageout (&ogg->sync, &page);
    if (ret == 0) {
      GST_DEBUG_OBJECT (ogg, "need more data");
      break;
    } else if (ret == -1) {
      GST_DEBUG_OBJECT (ogg, "discont in pages");
      ogg->discont = TRUE;
    } else {
      /* new unknown stream, init the ogg stream with the serial number of the
       * page. */
      if (ogg->serial == -1) {
        ogg->serial = ogg_page_serialno (&page);
        ogg_stream_init (&ogg->stream, ogg->serial);
      }

      /* submit page */
      if (ogg_stream_pagein (&ogg->stream, &page) != 0) {
        GST_WARNING_OBJECT (ogg, "ogg stream choked on page resetting stream");
        ogg_sync_reset (&ogg->sync);
        ogg->discont = TRUE;
        continue;
      }

      /* try to get as many packets as possible out of the page */
      do {
        ogg_packet packet;

        ret = ogg_stream_packetout (&ogg->stream, &packet);
        GST_LOG_OBJECT (ogg, "packetout gave %d", ret);
        switch (ret) {
          case 0:
            break;
          case -1:
            /* out of sync, We mark a DISCONT. */
            ogg->discont = TRUE;
            break;
          case 1:
            result = gst_ogg_avi_parse_push_packet (ogg, &packet);
            if (result != GST_FLOW_OK)
              goto done;
            break;
          default:
            GST_WARNING_OBJECT (ogg,
                "invalid return value %d for ogg_stream_packetout, resetting stream",
                ret);
            break;
        }
      }
      while (ret != 0);
    }
  }
  while (ret != 0);

done:
  return result;
}
示例#15
0
文件: speex.c 项目: jonsafari/mocp
static int spx_seek (void *prv_data, int sec)
{
	struct spx_data *data = (struct spx_data *)prv_data;
	off_t begin = 0, end, old_pos;

	assert (sec >= 0);

	end = io_file_size (data->stream);
	if (end == -1)
		return -1;
	old_pos = io_tell (data->stream);

	debug ("Seek request to %ds", sec);

	while (1) {
		off_t middle = (end + begin) / 2;
		ogg_int64_t granule_pos;
		int position_seconds;

		debug ("Seek to %"PRId64, middle);

		if (io_seek(data->stream, middle, SEEK_SET) == -1) {
			io_seek (data->stream, old_pos, SEEK_SET);
			ogg_stream_reset (&data->os);
			ogg_sync_reset (&data->oy);
			return -1;
		}

		debug ("Syncing...");

		/* Sync to page and read it */
		ogg_sync_reset (&data->oy);
		while (!io_eof(data->stream)) {
			if (ogg_sync_pageout(&data->oy, &data->og) == 1) {
				debug ("Sync");
				break;
			}

			if (!io_eof(data->stream)) {
				debug ("Need more data");
				get_more_data (data);
			}
		}

		if (io_eof(data->stream)) {
			debug ("EOF when syncing");
			return -1;
		}

		granule_pos = ogg_page_granulepos(&data->og);
		position_seconds = granule_pos / data->rate;

		debug ("We are at %ds", position_seconds);

		if (position_seconds == sec) {
			ogg_stream_pagein (&data->os, &data->og);
			debug ("We have it at granulepos %"PRId64, granule_pos);
			break;
		}
		else if (sec < position_seconds) {
			end = middle;
			debug ("going back");
		}
		else {
			begin = middle;
			debug ("going forward");
		}

		debug ("begin - end %"PRId64" - %"PRId64, begin, end);

		if (end - begin <= 200) {

			/* Can't find the exact position. */
			sec = position_seconds;
			break;
		}
	}

	ogg_sync_reset (&data->oy);
	ogg_stream_reset (&data->os);

	return sec;
}
示例#16
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 */
示例#17
0
文件: ogg.c 项目: 5in4/libsox.dll
static int
ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE* odata)
{	char *buffer ;
	int	 bytes, nn ;

	/* Call this here so it only gets called once, so no memory is leaked. */
	ogg_sync_init (&odata->osync) ;

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

	odata->codec = ogg_page_classify (psf, &odata->opage) ;

	switch (odata->codec)
	{	case OGG_VORBIS :
			psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
			return 0 ;

		case OGG_FLAC :
		case OGG_FLAC0 :
			psf->sf.format = SF_FORMAT_OGGFLAC ;
			return 0 ;

		case OGG_SPEEX :
			psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_SPEEX ;
			return 0 ;

		case OGG_PCM :
			psf_log_printf (psf, "Detected Ogg/PCM data. This is not supported yet.\n") ;
			return SFE_UNIMPLEMENTED ;

		default :
			break ;
		} ;

	psf_log_printf (psf, "This Ogg bitstream contains some uknown data type.\n") ;
	return SFE_UNIMPLEMENTED ;
} /* ogg_stream_classify */
示例#18
0
	long VideoClip_Theora::_seekPage(long targetFrame, bool returnKeyFrame)
	{
		uint64_t seekMin = 0;
		uint64_t seekMax = this->stream->getSize();
		long frame = 0;
		ogg_int64_t granule = 0;
		if (targetFrame == 0)
		{
			this->stream->seek(0);
		}
		char* buffer = NULL;
		int bytesRead = 0;
		if (targetFrame != 0)
		{
			for (int i = 0; i < 100; ++i)
			{
				ogg_sync_reset(&this->info.OggSyncState);
				this->stream->seek(seekMin / 2 + seekMax / 2); // do a binary search
				memset(&this->info.OggPage, 0, sizeof(ogg_page));
				ogg_sync_pageseek(&this->info.OggSyncState, &this->info.OggPage);
				while (i < 1000)
				{
					if (ogg_sync_pageout(&this->info.OggSyncState, &this->info.OggPage) == 1)
					{
						if (ogg_page_serialno(&this->info.OggPage) == this->info.TheoraStreamState.serialno)
						{
							granule = ogg_page_granulepos(&this->info.OggPage);
							if (granule >= 0)
							{
								frame = (long)th_granule_frame(this->info.TheoraDecoder, granule);
								if (frame < targetFrame && targetFrame - frame < 10)
								{
									// we're close enough, let's break this.
									i = 1000;
									break;
								}
								// we're not close enough, let's shorten the borders of the binary search
								if (targetFrame - 1 > frame)
								{
									seekMin = seekMin / 2 + seekMax / 2;
								}
								else
								{
									seekMax = seekMin / 2 + seekMax / 2;
								}
								break;
							}
						}
					}
					else
					{
						buffer = ogg_sync_buffer(&this->info.OggSyncState, BUFFER_SIZE);
						bytesRead = this->stream->read(buffer, BUFFER_SIZE);
						if (bytesRead == 0)
						{
							break;
						}
						ogg_sync_wrote(&this->info.OggSyncState, bytesRead);
					}
				}
			}
		}
		if (returnKeyFrame)
		{
			return (long)(granule >> this->info.TheoraInfo.keyframe_granule_shift);
		}
		ogg_sync_reset(&this->info.OggSyncState);
		memset(&this->info.OggPage, 0, sizeof(ogg_page));
		ogg_sync_pageseek(&this->info.OggSyncState, &this->info.OggPage);
		if (targetFrame == 0)
		{
			return -1;
		}
		this->stream->seek((seekMin + seekMax) / 2); // do a binary search
		return -1;
	}
示例#19
0
文件: ogg.c 项目: Erikhht/TCPMP
static void AfterSeek(ogg* p)
{
	ogg_sync_reset(p->OggSync);
}
示例#20
0
status_t
OggReader::FindLastPages()
{
	TRACE("OggReader::FindLastPages\n");
	bigtime_t start_time = system_time();

	status_t result = B_ERROR;

	const int read_size = 256*256;

	ogg_page page;
	ogg_sync_state sync;
	ogg_sync_init(&sync);

	off_t right = fSeekable->Seek(0, SEEK_END);
	off_t left = right;
	// we assume the common case is that the last pages are near the end
	uint serial_count = 0;
	while (serial_count < fCookies.size()) {
		int offset;
		ssize_t bytes = 0;
		while ((offset = ogg_sync_pageseek(&sync, &page)) <= 0) {
			left += -offset;
			if (offset == 0) {
				off_t pos = fSeekable->Position();
				if (pos >= right || bytes == 0) {
					if (left == 0) {
						TRACE("OggReader::FindLastPages: couldn't find some stream's page!!!\n");
						goto done;
					}
					left = max_c(0, left - read_size);
					result = fSeekable->Seek(left, SEEK_SET);
					if (result < 0) {
						goto done;
					}
					ogg_sync_reset(&sync);
				}
				char * buffer = ogg_sync_buffer(&sync, read_size);
				bytes = fSeekable->Read(buffer, read_size);
				if (bytes < 0) {
					TRACE("OggReader::FindLastPages: Read: error\n");
					result = bytes;
					goto done;
				}
				if (ogg_sync_wrote(&sync, bytes) != 0) {
					TRACE("OggReader::FindLastPages: ogg_sync_wrote failed?: error\n");
					goto done;
				}
			}
		}
		off_t current = left;
		do {
			// found a page at "current"
			long serialno = ogg_page_serialno(&page);
			OggSeekable * track = dynamic_cast<OggSeekable*>(fTracks[serialno]);
			if (track == 0) {
				TRACE("OggReader::FindLastPages: unknown serialno == TODO: chaining?\n");
			} else {
				if (track->GetLastPagePosition() == 0) {
					serial_count++;
				}
				track->SetLastPagePosition(current);
			}
			current += page.header_len + page.body_len;
		} while ((current < right) && (ogg_sync_pageout(&sync, &page) == 1));
		right = left;
		ogg_sync_reset(&sync);
	}
	result = B_OK;
done:
	ogg_sync_clear(&sync);
	TRACE("OggReader::FindLastPages took %lld microseconds\n", system_time() - start_time);

	return result;
}
示例#21
0
void test_pack(const int *pl, const int **headers){
  unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
  long inptr=0;
  long outptr=0;
  long deptr=0;
  long depacket=0;
  long granule_pos=7,pageno=0;
  int i,j,packets,pageout=0;
  int eosflag=0;
  int bosflag=0;

  ogg_stream_reset(&os_en);
  ogg_stream_reset(&os_de);
  ogg_sync_reset(&oy);

  for(packets=0;;packets++)if(pl[packets]==-1)break;

  for(i=0;i<packets;i++){
    /* construct a test packet */
    ogg_packet op;
    int len=pl[i];
    
    op.packet=data+inptr;
    op.bytes=len;
    op.e_o_s=(pl[i+1]<0?1:0);
    op.granulepos=granule_pos;

    granule_pos+=1024;

    for(j=0;j<len;j++)data[inptr++]=i+j;

    /* submit the test packet */
    ogg_stream_packetin(&os_en,&op);

    /* retrieve any finished pages */
    {
      ogg_page og;
      
      while(ogg_stream_pageout(&os_en,&og)){
	/* We have a page.  Check it carefully */

	fprintf(stderr,"%ld, ",pageno);

	if(headers[pageno]==NULL){
	  fprintf(stderr,"coded too many pages!\n");
	  exit(1);
	}

	check_page(data+outptr,headers[pageno],&og);

	outptr+=og.body_len;
	pageno++;

	/* have a complete page; submit it to sync/decode */

	{
	  ogg_page og_de;
	  ogg_packet op_de,op_de2;
	  char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
	  memcpy(buf,og.header,og.header_len);
	  memcpy(buf+og.header_len,og.body,og.body_len);
	  ogg_sync_wrote(&oy,og.header_len+og.body_len);

	  while(ogg_sync_pageout(&oy,&og_de)>0){
	    /* got a page.  Happy happy.  Verify that it's good. */
	    
	    check_page(data+deptr,headers[pageout],&og_de);
	    deptr+=og_de.body_len;
	    pageout++;

	    /* submit it to deconstitution */
	    ogg_stream_pagein(&os_de,&og_de);

	    /* packets out? */
	    while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
	      ogg_stream_packetpeek(&os_de,NULL);
	      ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
	      
	      /* verify peek and out match */
	      if(memcmp(&op_de,&op_de2,sizeof(op_de))){
		fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
			depacket);
		exit(1);
	      }

	      /* verify the packet! */
	      /* check data */
	      if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
		fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
			depacket);
		exit(1);
	      }
	      /* check bos flag */
	      if(bosflag==0 && op_de.b_o_s==0){
		fprintf(stderr,"b_o_s flag not set on packet!\n");
		exit(1);
	      }
	      if(bosflag && op_de.b_o_s){
		fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
		exit(1);
	      }
	      bosflag=1;
	      depacket+=op_de.bytes;
	      
	      /* check eos flag */
	      if(eosflag){
		fprintf(stderr,"Multiple decoded packets with eos flag!\n");
		exit(1);
	      }

	      if(op_de.e_o_s)eosflag=1;

	      /* check granulepos flag */
	      if(op_de.granulepos!=-1){
		fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
	      }
	    }
	  }
	}
      }
    }
  }
  _ogg_free(data);
  if(headers[pageno]!=NULL){
    fprintf(stderr,"did not write last page!\n");
    exit(1);
  }
  if(headers[pageout]!=NULL){
    fprintf(stderr,"did not decode last page!\n");
    exit(1);
  }
  if(inptr!=outptr){
    fprintf(stderr,"encoded page data incomplete!\n");
    exit(1);
  }
  if(inptr!=deptr){
    fprintf(stderr,"decoded page data incomplete!\n");
    exit(1);
  }
  if(inptr!=depacket){
    fprintf(stderr,"decoded packet data incomplete!\n");
    exit(1);
  }
  if(!eosflag){
    fprintf(stderr,"Never got a packet with EOS set!\n");
    exit(1);
  }
  fprintf(stderr,"ok.\n");
}
示例#22
0
文件: opus.c 项目: ifroz/rockbox
static int64_t seek_backwards(ogg_sync_state *oy, ogg_page *og,
                                  int64_t wantedpos)
{
    int64_t crofs;
    int64_t *curoffset=&crofs;
    *curoffset=ci->curpos;
    int64_t begin=*curoffset;
    int64_t end=begin;
    int64_t ret;
    int64_t offset=-1;
    int64_t avgpagelen=-1;
    int64_t lastgranule=-1;

    short time = -1;

    while (offset == -1) {

        begin -= SEEK_CHUNKSIZE;

        if (begin < 0) {
            if (time < 0) {
                begin = 0;
                time++;
            } else {
                LOGF("Can't seek that early:%lld\n",begin);
                return -3;  /* too early */
            }
        }

        *curoffset = begin;

        ci->seek_buffer(*curoffset);

        ogg_sync_reset(oy);

        lastgranule = -1;

        while (*curoffset < end) {
            ret = get_next_page(oy,og,end-*curoffset);

            if (ret > 0) {
                if (lastgranule != -1) {
                    if (avgpagelen < 0)
                        avgpagelen = (ogg_page_granulepos(og)-lastgranule);
                    else
                       avgpagelen=((ogg_page_granulepos(og)-lastgranule)
                                   + avgpagelen) / 2;
                }

                lastgranule=ogg_page_granulepos(og);

                if ((lastgranule - (avgpagelen/4)) < wantedpos &&
                    (lastgranule + avgpagelen + (avgpagelen/4)) > wantedpos) {

                    /*wanted offset found Yeay!*/

                    /*LOGF("GnPagefound:%d,%d,%d,%d\n",ret,
                           lastgranule,wantedpos,avgpagelen);*/

                    return ret;

                } else if (lastgranule > wantedpos) {  /*too late, seek more*/
                    if (offset != -1) {
                        LOGF("Toolate, returnanyway:%lld,%lld,%lld,%lld\n",
                             ret,lastgranule,wantedpos,avgpagelen);
                        return ret;
                    }
                    break;
                } else{ /*if (ogg_page_granulepos(&og)<wantedpos)*/
                    /*too early*/
                    offset = ret;
                    continue;
                }
            } else if (ret == -3) 
                return(-3);
            else if (ret<=0)
                break;
            else if (*curoffset < end) {
                /*this should not be possible*/

                //LOGF("Seek:get_earlier_page:Offset:not_cached by granule:"\"%d,%d,%d,%d,%d\n",*curoffset,end,begin,wantedpos,curpos);

                offset=ret;
            }
        }
    }
    return -1;
}
示例#23
0
static int decode(quicktime_t *file, 
					int16_t *output_i, 
					float *output_f, 
					long samples, 
					int track, 
					int channel)
{
	int result = 0;
	int bytes;
	int i, j;
	quicktime_audio_map_t *track_map = &(file->atracks[track]);
	quicktime_trak_t *trak = track_map->track;
	quicktime_vorbis_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
	long current_position = track_map->current_position;
	long end_position = current_position + samples;
  	unsigned char *buffer;
// End of data in ogg buffer
	int eos = 0;
// End of file
	int eof = 0;
	float *pcm;
	int have_chunk = 0;


	if(samples > OUTPUT_ALLOCATION)
		printf("vorbis.c decode: can't read more than %p samples at a time.\n", OUTPUT_ALLOCATION);



	if(output_i) bzero(output_i, sizeof(int16_t) * samples);
	if(output_f) bzero(output_f, sizeof(float) * samples);







// Seeked outside output buffer's range or not initialized: restart
	if(current_position < codec->output_position - codec->output_size ||
		current_position > codec->output_position ||
		!codec->decode_initialized)
	{

		quicktime_chunk_of_sample(&codec->output_position, 
			&codec->chunk, 
			trak, 
			current_position);
// We know the first ogg packet in the chunk has a pcm_offset from the encoding.

		codec->output_size = 0;
		codec->output_end = 0;
		codec->chunk_samples = 0;



	
// Initialize and load initial buffer for decoding
		if(!codec->decode_initialized)
		{
			int init_chunk = 1;
			codec->decode_initialized = 1;

			codec->output = malloc(sizeof(float*) * track_map->channels);
			for(i = 0; i < track_map->channels; i++)
			{
				codec->output[i] = malloc(sizeof(float) * OUTPUT_ALLOCATION);
			}

			codec->output_allocated = OUTPUT_ALLOCATION;

        	ogg_sync_init(&codec->dec_oy); /* Now we can read pages */




			READ_CHUNK(init_chunk);
			init_chunk++;

   	 		if(ogg_sync_pageout(&codec->dec_oy, &codec->dec_og)!=1)
			{
				fprintf(stderr, "decode: ogg_sync_pageout: Must not be Vorbis data\n");
				return 1;
			}


    		ogg_stream_init(&codec->dec_os, ogg_page_serialno(&codec->dec_og));
    		vorbis_info_init(&codec->dec_vi);
    		vorbis_comment_init(&codec->dec_vc);

    		if(ogg_stream_pagein(&codec->dec_os, &codec->dec_og) < 0)
			{
    	  		fprintf(stderr,"decode: ogg_stream_pagein: stream version mismatch perhaps.\n");
    	  		return 1;
    		}

			if(ogg_stream_packetout(&codec->dec_os, &codec->dec_op) != 1)
			{
				fprintf(stderr, "decode: ogg_stream_packetout: Must not be Vorbis data\n");
    	  		return 1;
			}

			if(vorbis_synthesis_headerin(&codec->dec_vi, &codec->dec_vc, &codec->dec_op) < 0)
			{
				fprintf(stderr, "decode: vorbis_synthesis_headerin: not a vorbis header\n");
				return 1;
			}


			i = 0;
			while(i < 2)
			{
				while(i < 2)
				{
					result = ogg_sync_pageout(&codec->dec_oy, &codec->dec_og);
					if(result == 0) break;

					if(result == 1)
					{
						ogg_stream_pagein(&codec->dec_os, &codec->dec_og);

						while(i < 2)
						{
							result = ogg_stream_packetout(&codec->dec_os, &codec->dec_op);

							if(result == 0) break;

							if(result < 0)
							{
								fprintf(stderr, "decode: ogg_stream_packetout: corrupt secondary header\n");
								return 1;
							}

							vorbis_synthesis_headerin(&codec->dec_vi, &codec->dec_vc, &codec->dec_op);
							i++;




						}
					}
				}

				if(i < 2)
				{
					READ_CHUNK(init_chunk);
					init_chunk++;
				}

// Header should never span more than one chunk so assume it's done here
			}

			vorbis_synthesis_init(&codec->dec_vd, &codec->dec_vi);
			vorbis_block_init(&codec->dec_vd, &codec->dec_vb);

// Also the first chunk needed in decoding so don't reread after this.
			if(codec->chunk == init_chunk - 1) 
			{
				have_chunk = 1;
				codec->chunk++;
			}
		}




// Don't already have initial chunk from header
		if(!have_chunk)
		{
// Get initial chunk for decoding at new location
// From vorbisfile.c
/* clear out decoding machine state */
			ogg_stream_clear(&codec->dec_os);
			vorbis_dsp_clear(&codec->dec_vd);
			vorbis_block_clear(&codec->dec_vb);
    		ogg_sync_reset(&codec->dec_oy);

    		ogg_stream_init(&codec->dec_os, ogg_page_serialno(&codec->dec_og));
        	ogg_sync_init(&codec->dec_oy);
			vorbis_synthesis_init(&codec->dec_vd, &codec->dec_vi);
			vorbis_block_init(&codec->dec_vd, &codec->dec_vb);


			READ_CHUNK(codec->chunk);
			codec->chunk++;
			have_chunk = 1;
		}
	}

// Assume the chunk exists by now and rely on libogg to say if it's out of
// data.
	have_chunk = 1;











// Read chunks until output buffer is on or after end_position
	result = 0;
	while(codec->output_position < end_position)
	{


// Read chunk to decode if it hasn't been read yet.
		if(!have_chunk)
		{
			codec->chunk_samples = 0;

			READ_CHUNK(codec->chunk);
			if(result) break;
			codec->chunk++;
		}

		eos = 0;
		while(!eos)
		{
			result = ogg_sync_pageout(&codec->dec_oy, &codec->dec_og);







// Need more data from chunk
			if(result == 0)
			{
// End of chunk
				eos = 1;
			}
			else
// This stage checks for OggS and a checksum error.
// It doesn't tell if it's the end of a chunk.  Need to manually parse OggS
// pages to figure out how big the chunk is.
			if(result < 0)
			{
//printf("ogg_sync_pageout=-1\n");
				;
			}
			else
			{
				ogg_stream_pagein(&codec->dec_os, &codec->dec_og);



				while(!eos)
				{
//printf("decode 7\n");
					result = ogg_stream_packetout(&codec->dec_os, &codec->dec_op);

//printf("decode 8 %d\n", result);
					if(result == 0)
					{
//printf("ogg_stream_packetout=0\n");
// End of page
						eos = 1;
					}
					else
// This stage doesn't check for OggS.
					if(result < 0)
					{
//printf("ogg_stream_packetout=-1\n");
					}
					else
					{
						float **pcm;







						if(vorbis_synthesis(&codec->dec_vb, &codec->dec_op) == 0)
						{
							vorbis_synthesis_blockin(&codec->dec_vd, 
								&codec->dec_vb);
						}


						while((result = vorbis_synthesis_pcmout(&codec->dec_vd, &pcm)) > 0)
						{
//printf("vorbis_synthesis_pcmout=%x\n", result);
							for(i = 0; i < track_map->channels; i++)
							{
								float *output_channel = codec->output[i];
								float *input_channel = pcm[i];
								int k = codec->output_end;

								for(j = 0; j < result; j++)
								{
									output_channel[k++] = input_channel[j];
									if(k >= codec->output_allocated)
										k = 0;
								}
								
								if(i == track_map->channels - 1) 
									codec->output_end = k;
							}
//printf("codec->output_end = %d\n", codec->output_end);

							codec->output_position += result;
							codec->output_size += result;
							codec->chunk_samples += result;
							if(codec->output_size > codec->output_allocated)
								codec->output_size = codec->output_allocated;
							vorbis_synthesis_read(&codec->dec_vd, result);
						}
					}
//printf("decode 11\n");
				}

// Reset end of page so it isn't interpreted as an end of chunk
				eos = 0;
			}
		}


// Next chunk
		if(eos)
		{
//printf("decode 12 got=%x\n", codec->chunk_samples);
			have_chunk = 0;
		}
	}


// Fill silence
	while(codec->output_position < end_position)
	{
		for(i = 0; i < track_map->channels; i++)
			codec->output[i][codec->output_end] = 0;
		
		codec->output_end++;
		if(codec->output_end >= codec->output_allocated)
			codec->output_end = 0;
		codec->output_position++;
	}
//printf("decode 15\n");


//printf("decode 2 codec->output_position=%lld codec->output_end=%d codec->output_size=%d\n", 
//	codec->output_position, codec->output_end, codec->output_size);

	current_position = track_map->current_position;
	i = codec->output_end - (codec->output_position - current_position);
	j = 0;
	while(i < 0) i += codec->output_allocated;
	pcm = codec->output[channel];

	if(output_i)
	{
		for( ; j < samples; j++)
		{
			int sample = pcm[i] * 32767;
			CLAMP(sample, -32768, 32767);
			output_i[j] = sample;

			i++;
			if(i >= codec->output_allocated) i = 0;
		}
	}
	else
	if(output_f)
	{
		for( ; j < samples; j++)
		{
			output_f[j] = pcm[i];
			i++;
			if(i >= codec->output_allocated) i = 0;
		}
	}
//printf("decode 16\n");

	return 0;
}
示例#24
0
文件: opus.c 项目: ifroz/rockbox
static int speex_seek_page_granule(int64_t pos, int64_t curpos,
                                   ogg_sync_state *oy, ogg_stream_state *os)
{
    /* TODO: Someone may want to try to implement seek to packet, 
             instead of just to page (should be more accurate, not be any 
             faster) */

    int64_t crofs;
    int64_t *curbyteoffset = &crofs;
    *curbyteoffset = ci->curpos;
    int64_t curoffset;
    curoffset = *curbyteoffset;
    int64_t offset = 0;
    ogg_page og = {0,0,0,0};
    int64_t avgpagelen = -1;
    int64_t lastgranule = -1;
#if 0
    if(abs(pos-curpos)>10000 && headerssize>0 && curoffset-headerssize>10000) {
        /* if seeking for more that 10sec,
           headersize is known & more than 10kb is played,
           try to guess a place to seek from the number of
           bytes playe for this position, this works best when 
           the bitrate is relativly constant.
         */

        curoffset = (((*curbyteoffset-headerssize) * pos)/curpos)*98/100;
        if (curoffset < 0)
            curoffset=0;

        //int64_t toffset=curoffset;

        ci->seek_buffer(curoffset);

        ogg_sync_reset(oy);

        offset = get_next_page(oy,&og,-1);

        if (offset < 0) { /* could not find new page,use old offset */
            LOGF("Seek/guess/fault:%lld->-<-%d,%lld:%lld,%d,%ld,%d\n",
                 curpos,0,pos,offset,0,
                 ci->curpos,/*stream_length*/0);

            curoffset = *curbyteoffset;

            ci->seek_buffer(curoffset);

            ogg_sync_reset(oy);
        } else {
            if (ogg_page_granulepos(&og) == 0 && pos > 5000) {
                LOGF("SEEK/guess/fault:%lld->-<-%lld,%lld:%lld,%d,%ld,%d\n",
                     curpos,ogg_page_granulepos(&og),pos,
                     offset,0,ci->curpos,/*stream_length*/0);

                curoffset = *curbyteoffset;

                ci->seek_buffer(curoffset);

                ogg_sync_reset(oy);
            } else {
                curoffset = offset;
                curpos = ogg_page_granulepos(&og);
            }
        }
    }
#endif
    /* which way do we want to seek? */
    if (pos == 0) {  /* start */
        *curbyteoffset = 0;
        ci->seek_buffer(*curbyteoffset);
        ogg_sync_reset(oy);
        ogg_stream_reset(os);
        return 0;
    } else if (curpos > pos) {  /* backwards */
        offset = seek_backwards(oy,&og,pos);

        if (offset > 0) {
            *curbyteoffset = curoffset;
            return 1;
        }
    } else {  /* forwards */

        while ( (offset = get_next_page(oy,&og,-1)) > 0) {
            if (lastgranule != -1) {
               if (avgpagelen < 0)
                   avgpagelen = (ogg_page_granulepos(&og) - lastgranule);
               else
                   avgpagelen = ((ogg_page_granulepos(&og) - lastgranule)
                                 + avgpagelen) / 2;
            }

            lastgranule = ogg_page_granulepos(&og);

            if ( ((lastgranule - (avgpagelen/4)) < pos && ( lastgranule + 
                  avgpagelen + (avgpagelen / 4)) > pos) ||
                 lastgranule > pos) {

                /*wanted offset found Yeay!*/

                *curbyteoffset = offset;

                return offset;
            }
        }
    }

    ci->seek_buffer(*curbyteoffset);

    ogg_sync_reset(oy);

    LOGF("Seek failed:%lld\n", offset);

    return -1;
}
示例#25
0
	void VideoClip_Theora::_load(DataSource* source)
	{
#ifdef _DEBUG
		log("-----");
#endif
		this->stream = source;
		this->_readTheoraVorbisHeaders();
		this->info.TheoraDecoder = th_decode_alloc(&this->info.TheoraInfo, this->info.TheoraSetup);
		this->width = this->info.TheoraInfo.frame_width;
		this->height = this->info.TheoraInfo.frame_height;
		this->subFrameWidth = this->info.TheoraInfo.pic_width;
		this->subFrameHeight = this->info.TheoraInfo.pic_height;
		this->subFrameX = this->info.TheoraInfo.pic_x;
		this->subFrameY = this->info.TheoraInfo.pic_y;
		this->stride = this->getWidth();
		if (this->useStride)
		{
			this->stride = potCeil(this->stride);
		}
		this->fps = this->info.TheoraInfo.fps_numerator / (float)this->info.TheoraInfo.fps_denominator;
#ifdef _DEBUG
		log("width: " + str(this->width) + ", height: " + str(this->height) + ", fps: " + str((int)this->getFps()));
#endif
		this->frameQueue = new FrameQueue(this);
		this->frameQueue->setSize(this->precachedFramesCount);
		// find out the duration of the file by seeking to the end
		// having ogg decode pages, extract the granule pos from
		// the last theora page and seek back to beginning of the file
		char* buffer = NULL;
		int bytesRead = 0;
		uint64_t streamSize = this->stream->getSize();
		uint64_t seekPos = 0;
		int result = 0;
		ogg_int64_t granule = 0;
		for (unsigned int i = 1; i <= 50; ++i)
		{
			ogg_sync_reset(&this->info.OggSyncState);
			seekPos = (BUFFER_SIZE * i > streamSize ? 0 : streamSize - BUFFER_SIZE * i);
			this->stream->seek(seekPos);
			buffer = ogg_sync_buffer(&this->info.OggSyncState, BUFFER_SIZE * i);
			bytesRead = this->stream->read(buffer, BUFFER_SIZE * i);
			ogg_sync_wrote(&this->info.OggSyncState, bytesRead);
			ogg_sync_pageseek(&this->info.OggSyncState, &this->info.OggPage);
			while (true)
			{
				result = ogg_sync_pageout(&this->info.OggSyncState, &this->info.OggPage);
				if (result == 0)
				{
					break;
				}
				// if page is not a theora page or page is unsynced(-1), skip it
				if (result == -1 || ogg_page_serialno(&this->info.OggPage) != this->info.TheoraStreamState.serialno)
				{
					continue;
				}
				granule = ogg_page_granulepos(&this->info.OggPage);
				if (granule >= 0)
				{
					this->framesCount = (int)th_granule_frame(this->info.TheoraDecoder, granule) + 1;
				}
				else if (this->framesCount > 0)
				{
					++this->framesCount; // append delta frames at the end to get the exact number
				}
			}
			if (this->framesCount > 0 || streamSize < BUFFER_SIZE * i)
			{
				break;
			}
		}
		if (this->framesCount < 0)
		{
			log("unable to determine file duration!");
		}
		else
		{
			this->duration = this->framesCount / this->fps;
#ifdef _DEBUG
			log("duration: " + strf(this->duration) + " seconds");
#endif
		}
		// restore to beginning of stream.
		ogg_sync_reset(&this->info.OggSyncState);
		this->stream->seek(0);
		if (this->vorbisStreams > 0) // if there is no audio interface factory defined, even though the video clip might have audio, it will be ignored
		{
			vorbis_synthesis_init(&this->info.VorbisDSPState, &this->info.VorbisInfo);
			vorbis_block_init(&this->info.VorbisDSPState, &this->info.VorbisBlock);
			this->audioChannelsCount = this->info.VorbisInfo.channels;
			this->audioFrequency = (int) this->info.VorbisInfo.rate;
			// create an audio interface instance if available
			AudioInterfaceFactory* audioInterfaceFactory = theoraplayer::manager->getAudioInterfaceFactory();
			if (audioInterfaceFactory != NULL)
			{
				this->setAudioInterface(audioInterfaceFactory->createInstance(this, this->audioChannelsCount, this->audioFrequency));
			}
		}
		this->frameDuration = 1.0f / this->getFps();
#ifdef _DEBUG
		log("-----");
#endif
	}
示例#26
0
int main(void){

  ogg_stream_init(&os_en,0x04030201);
  ogg_stream_init(&os_de,0x04030201);
  ogg_sync_init(&oy);

  /* Exercise each code path in the framing code.  Also verify that
     the checksums are working.  */

  {
    /* 17 only */
    const int packets[]={17, -1};
    const int *headret[]={head1_0,NULL};
    
    fprintf(stderr,"testing single page encoding... ");
    test_pack(packets,headret);
  }

  {
    /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
    const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
    const int *headret[]={head1_1,head2_1,NULL};
    
    fprintf(stderr,"testing basic page encoding... ");
    test_pack(packets,headret);
  }

  {
    /* nil packets; beginning,middle,end */
    const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
    const int *headret[]={head1_2,head2_2,NULL};
    
    fprintf(stderr,"testing basic nil packets... ");
    test_pack(packets,headret);
  }

  {
    /* large initial packet */
    const int packets[]={4345,259,255,-1};
    const int *headret[]={head1_3,head2_3,NULL};
    
    fprintf(stderr,"testing initial-packet lacing > 4k... ");
    test_pack(packets,headret);
  }

  {
    /* continuing packet test */
    const int packets[]={0,4345,259,255,-1};
    const int *headret[]={head1_4,head2_4,head3_4,NULL};
    
    fprintf(stderr,"testing single packet page span... ");
    test_pack(packets,headret);
  }

  /* page with the 255 segment limit */
  {

    const int packets[]={0,10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,50,-1};
    const int *headret[]={head1_5,head2_5,head3_5,NULL};
    
    fprintf(stderr,"testing max packet segments... ");
    test_pack(packets,headret);
  }

  {
    /* packet that overspans over an entire page */
    const int packets[]={0,100,9000,259,255,-1};
    const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
    
    fprintf(stderr,"testing very large packets... ");
    test_pack(packets,headret);
  }

  {
    /* term only page.  why not? */
    const int packets[]={0,100,4080,-1};
    const int *headret[]={head1_7,head2_7,head3_7,NULL};
    
    fprintf(stderr,"testing zero data page (1 nil packet)... ");
    test_pack(packets,headret);
  }



  {
    /* build a bunch of pages for testing */
    unsigned char *data=_ogg_malloc(1024*1024);
    int pl[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1};
    int inptr=0,i,j;
    ogg_page og[5];
    
    ogg_stream_reset(&os_en);

    for(i=0;pl[i]!=-1;i++){
      ogg_packet op;
      int len=pl[i];
      
      op.packet=data+inptr;
      op.bytes=len;
      op.e_o_s=(pl[i+1]<0?1:0);
      op.granulepos=(i+1)*1000;

      for(j=0;j<len;j++)data[inptr++]=i+j;
      ogg_stream_packetin(&os_en,&op);
    }

    _ogg_free(data);

    /* retrieve finished pages */
    for(i=0;i<5;i++){
      if(ogg_stream_pageout(&os_en,&og[i])==0){
	fprintf(stderr,"Too few pages output building sync tests!\n");
	exit(1);
      }
      copy_page(&og[i]);
    }

    /* Test lost pages on pagein/packetout: no rollback */
    {
      ogg_page temp;
      ogg_packet test;

      fprintf(stderr,"Testing loss of pages... ");

      ogg_sync_reset(&oy);
      ogg_stream_reset(&os_de);
      for(i=0;i<5;i++){
	memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
	       og[i].header_len);
	ogg_sync_wrote(&oy,og[i].header_len);
	memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
	ogg_sync_wrote(&oy,og[i].body_len);
      }

      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      /* skip */
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);

      /* do we get the expected results/packets? */
      
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,0,0,0);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,100,1,-1);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,4079,2,3000);
      if(ogg_stream_packetout(&os_de,&test)!=-1){
	fprintf(stderr,"Error: loss of page did not return error\n");
	exit(1);
      }
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,76,5,-1);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,34,6,-1);
      fprintf(stderr,"ok.\n");
    }

    /* Test lost pages on pagein/packetout: rollback with continuation */
    {
      ogg_page temp;
      ogg_packet test;

      fprintf(stderr,"Testing loss of pages (rollback required)... ");

      ogg_sync_reset(&oy);
      ogg_stream_reset(&os_de);
      for(i=0;i<5;i++){
	memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
	       og[i].header_len);
	ogg_sync_wrote(&oy,og[i].header_len);
	memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
	ogg_sync_wrote(&oy,og[i].body_len);
      }

      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      /* skip */
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);

      /* do we get the expected results/packets? */
      
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,0,0,0);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,100,1,-1);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,4079,2,3000);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,2956,3,4000);
      if(ogg_stream_packetout(&os_de,&test)!=-1){
	fprintf(stderr,"Error: loss of page did not return error\n");
	exit(1);
      }
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,300,13,14000);
      fprintf(stderr,"ok.\n");
    }
    
    /* the rest only test sync */
    {
      ogg_page og_de;
      /* Test fractional page inputs: incomplete capture */
      fprintf(stderr,"Testing sync on partial inputs... ");
      ogg_sync_reset(&oy);
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     3);
      ogg_sync_wrote(&oy,3);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      /* Test fractional page inputs: incomplete fixed header */
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
	     20);
      ogg_sync_wrote(&oy,20);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      /* Test fractional page inputs: incomplete header */
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
	     5);
      ogg_sync_wrote(&oy,5);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      /* Test fractional page inputs: incomplete body */
      
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
	     og[1].header_len-28);
      ogg_sync_wrote(&oy,og[1].header_len-28);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
      ogg_sync_wrote(&oy,1000);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
	     og[1].body_len-1000);
      ogg_sync_wrote(&oy,og[1].body_len-1000);
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
      
      fprintf(stderr,"ok.\n");
    }

    /* Test fractional page inputs: page + incomplete capture */
    {
      ogg_page og_de;
      fprintf(stderr,"Testing sync on 1+partial inputs... ");
      ogg_sync_reset(&oy); 

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     og[1].header_len);
      ogg_sync_wrote(&oy,og[1].header_len);

      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     20);
      ogg_sync_wrote(&oy,20);
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
      if(ogg_sync_pageout(&oy,&og_de)>0)error();

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
	     og[1].header_len-20);
      ogg_sync_wrote(&oy,og[1].header_len-20);
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();

      fprintf(stderr,"ok.\n");
    }
    
    /* Test recapture: garbage + page */
    {
      ogg_page og_de;
      fprintf(stderr,"Testing search for capture... ");
      ogg_sync_reset(&oy); 
      
      /* 'garbage' */
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     og[1].header_len);
      ogg_sync_wrote(&oy,og[1].header_len);

      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);

      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
	     20);
      ogg_sync_wrote(&oy,20);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
      if(ogg_sync_pageout(&oy,&og_de)>0)error();

      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
	     og[2].header_len-20);
      ogg_sync_wrote(&oy,og[2].header_len-20);
      memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
	     og[2].body_len);
      ogg_sync_wrote(&oy,og[2].body_len);
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();

      fprintf(stderr,"ok.\n");
    }

    /* Test recapture: page + garbage + page */
    {
      ogg_page og_de;
      fprintf(stderr,"Testing recapture... ");
      ogg_sync_reset(&oy); 

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     og[1].header_len);
      ogg_sync_wrote(&oy,og[1].header_len);

      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);

      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
	     og[2].header_len);
      ogg_sync_wrote(&oy,og[2].header_len);

      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
	     og[2].header_len);
      ogg_sync_wrote(&oy,og[2].header_len);

      if(ogg_sync_pageout(&oy,&og_de)<=0)error();

      memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
	     og[2].body_len-5);
      ogg_sync_wrote(&oy,og[2].body_len-5);

      memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
	     og[3].header_len);
      ogg_sync_wrote(&oy,og[3].header_len);

      memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
	     og[3].body_len);
      ogg_sync_wrote(&oy,og[3].body_len);

      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();

      fprintf(stderr,"ok.\n");
    }
  }    

  return(0);
}
示例#27
0
文件: opus.c 项目: ifroz/rockbox
/* this is called for each file to process */
enum codec_status codec_run(void)
{
    int error = CODEC_ERROR;
    intptr_t param;
    ogg_sync_state oy;
    ogg_page og;
    ogg_packet op;
    ogg_stream_state os;
    int64_t page_granule = 0;
    int stream_init = 0;
    int sample_rate = 48000;
    OpusDecoder *st = NULL;
    OpusHeader header;
    int ret;
    unsigned long strtoffset = ci->id3->offset;
    int skip = 0;
    int64_t seek_target;
    uint64_t granule_pos;

    ogg_malloc_init();

    global_stack = 0;

#if defined(CPU_COLDFIRE)
    /* EMAC rounding is disabled because of MULT16_32_Q15, which will be
       inaccurate with rounding in its current incarnation */
    coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
#endif

    /* pre-init the ogg_sync_state buffer, so it won't need many reallocs */
    ogg_sync_init(&oy);
    oy.storage = 64*1024;
    oy.data = _ogg_malloc(oy.storage);

    /* allocate output buffer */
    uint16_t *output = (uint16_t*) _ogg_malloc(MAX_FRAME_SIZE*sizeof(uint16_t));

    ci->seek_buffer(0);
    ci->set_elapsed(0);

    while (1) {
        enum codec_command_action action = ci->get_command(&param);

        if (action == CODEC_ACTION_HALT)
            break;

        if (action == CODEC_ACTION_SEEK_TIME) {
            if (st != NULL) {
                /* calculate granule to seek to (including seek rewind) */
                seek_target = (48LL * param) + header.preskip;
                skip = MIN(seek_target, SEEK_REWIND);
                seek_target -= skip;

                LOGF("Opus seek page:%lld,%lld,%ld\n",
		            seek_target, page_granule, (long)param);
                speex_seek_page_granule(seek_target, page_granule, &oy, &os);
            }

            ci->set_elapsed(param);
            ci->seek_complete();
        }

        /*Get the ogg buffer for writing*/
        if (get_more_data(&oy) < 1) {
            goto done;
        }

        /* Loop for all complete pages we got (most likely only one) */
        while (ogg_sync_pageout(&oy, &og) == 1) {
            if (stream_init == 0) {
                ogg_stream_init(&os, ogg_page_serialno(&og));
                stream_init = 1;
            }

            /* Add page to the bitstream */
            ogg_stream_pagein(&os, &og);

            page_granule = ogg_page_granulepos(&og);
            granule_pos = page_granule;

            /* Do this to avoid allocating space for huge comment packets
               (embedded Album Art) */
            if(os.packetno == 1 && ogg_stream_packetpeek(&os, &op) != 1){
              ogg_sync_reset(&oy);
            }

            while ((ogg_stream_packetout(&os, &op) == 1) && !op.e_o_s) {
                if (op.packetno == 0){
                    /* identification header */
                
                    if (opus_header_parse(op.packet, op.bytes, &header) == 0) {
                        LOGF("Could not parse header");
                        goto done;
                    }
                    skip = header.preskip;

                    st = opus_decoder_create(sample_rate, header.channels, &ret);
                    if (ret != OPUS_OK) {
                        LOGF("opus_decoder_create failed %d", ret);
                        goto done;
                    }
                    LOGF("Decoder inited");

                    codec_set_replaygain(ci->id3);

                    opus_decoder_ctl(st, OPUS_SET_GAIN(header.gain));

                    ci->configure(DSP_SET_FREQUENCY, sample_rate);
                    ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
                    ci->configure(DSP_SET_STEREO_MODE, (header.channels == 2) ?
                        STEREO_INTERLEAVED : STEREO_MONO);

                } else if (op.packetno == 1) {
                    /* Comment header */
                } else {
                    if (strtoffset) {
                        ci->seek_buffer(strtoffset);
                        ogg_sync_reset(&oy);
                        strtoffset = 0;
                        break;//next page
                    }

                    /* report progress */
                    ci->set_elapsed((granule_pos - header.preskip) / 48);

                    /* Decode audio packets */
                    ret = opus_decode(st, op.packet, op.bytes, output, MAX_FRAME_SIZE, 0);

                    if (ret > 0) {
                        if (skip > 0) {
                            if (ret <= skip) {
                                /* entire output buffer is skipped */
                                skip -= ret;
                                ret = 0;
                            } else {
                                /* part of output buffer is played */
                                ret -= skip;
                                ci->pcmbuf_insert(&output[skip * header.channels], NULL, ret);
                                skip = 0;
                            }
                        } else {
                            /* entire buffer is played */
                            ci->pcmbuf_insert(output, NULL, ret);
                        }
                        granule_pos += ret;
                    } else {
                        if (ret < 0) {
                            LOGF("opus_decode failed %d", ret);
                            goto done;
                        }
                        break;
                    }
                }
            }
        }
    }
    LOGF("Returned OK");
    error = CODEC_OK;
done:
    ogg_malloc_destroy();
    return error;
}