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; }
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; }
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); };
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; }
/* 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"); } }
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; } }
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; }
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; }
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(); } }
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; }
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; }
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 */
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; }
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; }
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 */
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 */
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; }
static void AfterSeek(ogg* p) { ogg_sync_reset(p->OggSync); }
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; }
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"); }
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; }
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; }
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; }
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 }
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); }
/* 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(¶m); 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; }