nsresult nsOggCodecState::Reset() { if (ogg_stream_reset(&mState) != 0) { return NS_ERROR_FAILURE; } mBuffer.Erase(); return NS_OK; }
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 DGVideo::unload() { if (_isLoaded) { _isLoaded = false; _state = DGVideoInitial; _theoraInfo->videobuf_ready = 0; _theoraInfo->videobuf_granulepos -= 1; _theoraInfo->videobuf_time = 0; if (_theoraInfo->theora_p) { // Rewind and reset fseek(_handle, (long)_theoraInfo->bos * 8, SEEK_SET); ogg_stream_reset(&_theoraInfo->to); ogg_stream_clear(&_theoraInfo->to); theora_clear(&_theoraInfo->td); theora_comment_clear(&_theoraInfo->tc); theora_info_clear(&_theoraInfo->ti); } ogg_sync_clear(&_theoraInfo->oy); _theoraInfo->theora_p = 0; free(_currentFrame.data); fclose(_handle); } }
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; }
nsresult OggCodecState::Reset() { if (ogg_stream_reset(&mState) != 0) { return NS_ERROR_FAILURE; } mPackets.Erase(); ClearUnstamped(); return NS_OK; }
static PyObject * py_ogg_ogg_stream_reset(PyObject *self, PyObject *args) { int c_out; int size; ogg_stream_state * os; PyArg_ParseTuple(args, "s#", &os, &size); c_out = ogg_stream_reset(os); return Py_BuildValue("i", c_out); };
void CAOggFLACDecoder::BDCReset() { mFramesBufferedList.clear(); complete_pages = 0; if (mCompressionInitialized) ogg_stream_reset(&mO_st); CAFLACDecoder::BDCReset(); }
void DGVideo::stop() { if (_state == DGVideoPlaying) { _state = DGVideoStopped; // Rewind fseek(_handle, (long)_theoraInfo->bos * 8, SEEK_SET); ogg_stream_reset(&_theoraInfo->to); } }
/* * Class: org_tritonus_lowlevel_ogg_StreamState * Method: reset * Signature: ()I */ JNIEXPORT jint JNICALL Java_org_tritonus_lowlevel_ogg_StreamState_reset (JNIEnv* env, jobject obj) { ogg_stream_state* handle; int nReturn; if (debug_flag) { fprintf(debug_file, "Java_org_tritonus_lowlevel_ogg_StreamState_reset(): begin\n"); } handle = getHandle(env, obj); nReturn = ogg_stream_reset(handle); if (debug_flag) { fprintf(debug_file, "Java_org_tritonus_lowlevel_ogg_StreamState_reset(): end\n"); } return nReturn; }
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(); } }
void CAOggFLACDecoder::InitializeCompressionSettings() { if (mCookie != NULL) { if (mCompressionInitialized) ogg_stream_clear(&mO_st); OggSerialNoAtom *atom = reinterpret_cast<OggSerialNoAtom*> (mCookie); if (EndianS32_BtoN(atom->type) == kCookieTypeOggSerialNo && EndianS32_BtoN(atom->size) <= mCookieSize) { ogg_stream_init(&mO_st, EndianS32_BtoN(atom->serialno)); } } ogg_stream_reset(&mO_st); CAFLACDecoder::InitializeCompressionSettings(); }
int DGVideo::_prepareFrame() { while (_state == DGVideoPlaying) { while (_theoraInfo->theora_p && !_theoraInfo->videobuf_ready) { if (ogg_stream_packetout(&_theoraInfo->to, &_theoraInfo->op) > 0) { theora_decode_packetin(&_theoraInfo->td, &_theoraInfo->op); _theoraInfo->videobuf_granulepos = _theoraInfo->td.granulepos; _theoraInfo->videobuf_time = theora_granule_time(&_theoraInfo->td, _theoraInfo->videobuf_granulepos); _theoraInfo->videobuf_ready = 1; if (!_theoraInfo->bos) { _theoraInfo->bos = _theoraInfo->td.granulepos; } } else break; } if (!_theoraInfo->videobuf_ready && feof(_handle)) { if (_isLoopable) { // This is the begin of stream (granule position) * 8 bits (in bytes) fseek(_handle, (long)_theoraInfo->bos * 8, SEEK_SET); ogg_stream_reset(&_theoraInfo->to); } else { this->stop(); } break; } if (!_theoraInfo->videobuf_ready) { _bufferData(&_theoraInfo->oy); while (ogg_sync_pageout(&_theoraInfo->oy, &_theoraInfo->og) > 0) { _queuePage(_theoraInfo, &_theoraInfo->og); } } else { _theoraInfo->videobuf_ready = 0; return 1; } _theoraInfo->videobuf_ready = 0; } return 0; }
static void *vorbis_thread(void *arg) { int res, n; char *oggbuf; time_t now; VORBIS_FEED *feed; feed = (VORBIS_FEED *)arg; pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_mutex_lock(&(feed->base.thread_lock)); if (vorbis_synthesis_init(&(feed->vd), &(feed->vi)) != 0) { logmsg("vorbis init failed\n"); return NULL; } feed->base.running = 1; if (feeds == NULL) feeds = new_unit(); link_unit((MASH_UNIT *)feed, feeds); vorbis_block_init(&(feed->vd), &(feed->vb)); while (feed->base.running) { while (1) { res = ogg_sync_pageout(&(feed->oy), &(feed->og)); if (res == 0) break; if (res < 0) { logmsg("missing data\n"); continue; } res = ogg_stream_pagein(&(feed->os), &(feed->og)); if (res < 0) { ogg_stream_reset(&(feed->os)); ogg_stream_init(&(feed->os), ogg_page_serialno(&(feed->og))); now = time(NULL); logmsg("%s: bad ogg page\n", ctime(&now)); continue; } process_vorbis_packets(feed); } pthread_cond_wait(&(feed->base.data_ready), &(feed->base.thread_lock)); oggbuf = ogg_sync_buffer(&(feed->oy), BLOCKSIZE); n = read(feed->base.sock, oggbuf, BLOCKSIZE); ogg_sync_wrote(&(feed->oy), n); } pthread_mutex_unlock(&(feed->base.thread_lock)); return NULL; }
static bool vorbis_encoder_pre_tag(struct encoder *_encoder, G_GNUC_UNUSED GError **error) { struct vorbis_encoder *encoder = (struct vorbis_encoder *)_encoder; vorbis_analysis_wrote(&encoder->vd, 0); vorbis_encoder_blockout(encoder); /* reinitialize vorbis_dsp_state and vorbis_block to reset the end-of-stream marker */ vorbis_block_clear(&encoder->vb); vorbis_dsp_clear(&encoder->vd); vorbis_analysis_init(&encoder->vd, &encoder->vi); vorbis_block_init(&encoder->vd, &encoder->vb); ogg_stream_reset(&encoder->os); encoder->flush = true; return true; }
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; }
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 */
void VideoClip_Theora::_executeSeek() { #if _DEBUG log(this->name + " [seek]: seeking to frame " + str(this->seekFrame)); #endif int frame = 0; float time = this->seekFrame / getFps(); this->timer->seek(time); bool paused = this->timer->isPaused(); if (!paused) { this->timer->pause(); // pause until seeking is done } this->endOfFile = false; this->restarted = false; this->_resetFrameQueue(); // reset the video decoder. ogg_stream_reset(&this->info.TheoraStreamState); th_decode_free(this->info.TheoraDecoder); this->info.TheoraDecoder = th_decode_alloc(&this->info.TheoraInfo, this->info.TheoraSetup); Mutex::ScopeLock audioMutexLock; if (this->audioInterface != NULL) { audioMutexLock.acquire(this->audioMutex); ogg_stream_reset(&this->info.VorbisStreamState); vorbis_synthesis_restart(&this->info.VorbisDSPState); this->destroyAllAudioPackets(); } // first seek to desired frame, then figure out the location of the // previous key frame and seek to it. // then by setting the correct time, the decoder will skip N frames untill // we get the frame we want. frame = (int)this->_seekPage(this->seekFrame, 1); // find the key frame nearest to the target frame #ifdef _DEBUG // log(mName + " [seek]: nearest key frame for frame " + str(mSeekFrame) + " is frame: " + str(frame)); #endif this->_seekPage(std::max(0, frame - 1), 0); ogg_packet opTheora; ogg_int64_t granulePos; bool granuleSet = false; if (frame <= 1) { if (this->info.TheoraInfo.version_major == 3 && this->info.TheoraInfo.version_minor == 2 && this->info.TheoraInfo.version_subminor == 0) { granulePos = 0; } else { granulePos = 1; // because of difference in granule interpretation in theora streams 3.2.0 and newer ones } th_decode_ctl(this->info.TheoraDecoder, TH_DECCTL_SET_GRANPOS, &granulePos, sizeof(granulePos)); granuleSet = true; } // now that we've found the key frame that preceeds our desired frame, lets keep on decoding frames until we // reach our target frame. int status = 0; while (this->seekFrame != 0) { if (ogg_stream_packetout(&this->info.TheoraStreamState, &opTheora) > 0) { if (!granuleSet) { // theora decoder requires to set the granule pos after seek to be able to determine the current frame if (opTheora.granulepos < 0) { continue; // ignore prev delta frames until we hit a key frame } th_decode_ctl(this->info.TheoraDecoder, TH_DECCTL_SET_GRANPOS, &opTheora.granulepos, sizeof(opTheora.granulepos)); granuleSet = true; } status = th_decode_packetin(this->info.TheoraDecoder, &opTheora, &granulePos); if (status != 0 && status != TH_DUPFRAME) { continue; } frame = (int)th_granule_frame(this->info.TheoraDecoder, granulePos); if (frame >= this->seekFrame - 1) { break; } } else if (!this->_readData()) { log(this->name + " [seek]: fineseeking failed, _readData failed!"); return; } } #ifdef _DEBUG // log(mName + " [seek]: fineseeked to frame " + str(frame + 1) + ", requested: " + str(mSeekFrame)); #endif if (this->audioInterface != NULL) { // read audio data until we reach a timeStamp. this usually takes only one iteration, but just in case let's // wrap it in a loop float timeStamp = 0.0f; while (true) { timeStamp = this->_decodeAudio(); if (timeStamp >= 0) { break; } this->_readData(); } float rate = (float)this->audioFrequency * this->audioChannelsCount; float queuedTime = this->getAudioPacketQueueLength(); int trimmedCount = 0; // at this point there are only 2 possibilities: either we have too much packets and we have to delete // the first N ones, or we don't have enough, so let's fill the gap with silence. if (time > timeStamp - queuedTime) { while (this->audioPacketQueue != NULL) { if (time <= timeStamp - queuedTime + this->audioPacketQueue->samplesCount / rate) { trimmedCount = (int)((timeStamp - queuedTime + this->audioPacketQueue->samplesCount / rate - time) * rate); if (this->audioPacketQueue->samplesCount - trimmedCount <= 0) { this->destroyAudioPacket(this->popAudioPacket()); // if there's no data to be left, just destroy it } else { for (int i = trimmedCount, j = 0; i < this->audioPacketQueue->samplesCount; ++i, ++j) { this->audioPacketQueue->pcmData[j] = this->audioPacketQueue->pcmData[i]; } this->audioPacketQueue->samplesCount -= trimmedCount; } break; } queuedTime -= this->audioPacketQueue->samplesCount / rate; this->destroyAudioPacket(this->popAudioPacket()); } } // expand the first packet with silence. else if (this->audioPacketQueue != NULL) { int i = 0; int j = 0; int missingCount = (int)((timeStamp - queuedTime - time) * rate); if (missingCount > 0) { float* samples = new float[missingCount + this->audioPacketQueue->samplesCount]; if (missingCount > 0) { memset(samples, 0, missingCount * sizeof(float)); } for (j = 0; i < missingCount + this->audioPacketQueue->samplesCount; ++i, ++j) { samples[i] = this->audioPacketQueue->pcmData[j]; } delete[] this->audioPacketQueue->pcmData; this->audioPacketQueue->pcmData = samples; } } this->lastDecodedFrameNumber = this->seekFrame; this->readAudioSamples = (unsigned int)(timeStamp * this->audioFrequency); audioMutexLock.release(); } if (!paused) { this->timer->play(); } this->seekFrame = -1; }
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 */
int ov_raw_seek(OggVorbis_File *vf,long pos){ ogg_stream_state work_os; if(vf->ready_state<OPENED)return(OV_EINVAL); if(!vf->seekable) return(OV_ENOSEEK); /* don't dump machine if we can't seek */ if(pos<0 || pos>vf->offsets[vf->links])return(OV_EINVAL); /* clear out decoding machine state */ vf->pcm_offset=-1; _decode_clear(vf); _seek_helper(vf,pos); /* we need to make sure the pcm_offset is set, but we don't want to advance the raw cursor past good packets just to get to the first with a granulepos. That's not equivalent behavior to beginning decoding as immediately after the seek position as possible. So, a hack. We use two stream states; a local scratch state and a the shared vf->os stream state. We use the local state to scan, and the shared state as a buffer for later decode. Unfortuantely, on the last page we still advance to last packet because the granulepos on the last page is not necessarily on a packet boundary, and we need to make sure the granpos is correct. */ { ogg_page og; ogg_packet op; int lastblock=0; int accblock=0; int thisblock=-1; int eosflag=0; memset(&work_os,0,sizeof(work_os));/* so that it's safe to clear it later even if we don't init it */ while(1){ if(vf->ready_state==STREAMSET){ /* snarf/scan a packet if we can */ int result=ogg_stream_packetout(&work_os,&op); if(result>0){ if(vf->vi[vf->current_link].codec_setup) thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op); if(eosflag) ogg_stream_packetout(&vf->os,NULL); else if(lastblock)accblock+=(lastblock+thisblock)>>2; if(op.granulepos!=-1){ int i,link=vf->current_link; ogg_int64_t granulepos=op.granulepos; for(i=0;i<link;i++) granulepos+=vf->pcmlengths[i]; vf->pcm_offset=granulepos-accblock; break; } lastblock=thisblock; continue; } } if(!lastblock){ if(_get_next_page(vf,&og,-1)<0){ vf->pcm_offset=ov_pcm_total(vf,-1); break; } }else{ /* huh? Bogus stream with packets but no granulepos */ vf->pcm_offset=-1; break; } /* has our decoding just traversed a bitstream boundary? */ if(vf->ready_state==STREAMSET) if(vf->current_serialno!=ogg_page_serialno(&og)){ _decode_clear(vf); /* clear out stream state */ ogg_stream_clear(&work_os); } if(vf->ready_state<STREAMSET){ int link; vf->current_serialno=ogg_page_serialno(&og); for(link=0;link<vf->links;link++) if(vf->serialnos[link]==vf->current_serialno)break; if(link==vf->links)goto seek_error; /* sign of a bogus stream. error out, leave machine uninitialized */ vf->current_link=link; ogg_stream_init(&vf->os,vf->current_serialno); ogg_stream_reset(&vf->os); ogg_stream_init(&work_os,vf->current_serialno); ogg_stream_reset(&work_os); vf->ready_state=STREAMSET; } ogg_stream_pagein(&vf->os,&og); ogg_stream_pagein(&work_os,&og); eosflag=ogg_page_eos(&og); } }
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; }
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); }
static int64_t find_first_page( demux_t *p_demux, int64_t i_pos1, int64_t i_pos2, logical_stream_t *p_stream, int64_t *pi_kframe, int64_t *pi_frame ) { int64_t i_result; int64_t i_granulepos; int64_t i_bytes_to_read = i_pos2 - i_pos1 + 1; int64_t i_bytes_read; int64_t i_pages_checked = 0; int64_t i_packets_checked; demux_sys_t *p_sys = p_demux->p_sys; ogg_packet op; seek_byte( p_demux, i_pos1 ); if ( i_pos1 == p_stream->i_data_start ) { /* set a dummy granulepos at data_start */ *pi_kframe = p_stream->i_keyframe_offset; *pi_frame = p_stream->i_keyframe_offset; p_sys->b_page_waiting = true; return p_sys->i_input_position; } if ( i_bytes_to_read > OGGSEEK_BYTES_TO_READ ) i_bytes_to_read = OGGSEEK_BYTES_TO_READ; while ( 1 ) { if ( p_sys->i_input_position >= i_pos2 ) { /* we reached the end and found no pages */ *pi_frame=-1; return -1; } /* read next chunk */ if ( ! ( i_bytes_read = get_data( p_demux, i_bytes_to_read ) ) ) { /* EOF */ *pi_frame = -1; return -1; } i_bytes_to_read = OGGSEEK_BYTES_TO_READ; i_result = ogg_sync_pageseek( &p_sys->oy, &p_sys->current_page ); if ( i_result < 0 ) { /* found a page, sync to page start */ p_sys->i_input_position -= i_result; i_pos1 = p_sys->i_input_position; continue; } if ( i_result > 0 || ( i_result == 0 && p_sys->oy.fill > 3 && ! strncmp( (char *)p_sys->oy.data, "OggS" , 4 ) ) ) { i_pos1 = p_sys->i_input_position; break; } p_sys->i_input_position += i_bytes_read; }; seek_byte( p_demux, p_sys->i_input_position ); ogg_stream_reset( &p_stream->os ); while( 1 ) { if ( p_sys->i_input_position >= i_pos2 ) { /* reached the end of the search region and nothing was found */ *pi_frame = -1; return p_sys->i_input_position; } p_sys->b_page_waiting = false; if ( ! ( i_result = oggseek_read_page( p_demux ) ) ) { /* EOF */ *pi_frame = -1; return p_sys->i_input_position; } // found a page if ( p_stream->os.serialno != ogg_page_serialno( &p_sys->current_page ) ) { /* page is not for this stream */ p_sys->i_input_position += i_result; if ( ! i_pages_checked ) i_pos1 = p_sys->i_input_position; continue; } ogg_stream_pagein( &p_stream->os, &p_sys->current_page ); i_pages_checked++; i_packets_checked = 0; if ( ogg_stream_packetout( &p_stream->os, &op ) > 0 ) { i_packets_checked++; } if ( i_packets_checked ) { i_granulepos = ogg_page_granulepos( &p_sys->current_page ); oggseek_theora_index_entry_add( p_stream, i_granulepos, i_pos1 ); *pi_kframe = i_granulepos >> p_stream->i_granule_shift; *pi_frame = *pi_kframe + i_granulepos - ( *pi_kframe << p_stream->i_granule_shift ); p_sys->b_page_waiting = true; return i_pos1; } /* -> start of next page */ p_sys->i_input_position += i_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 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; }
int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno){ ogg_stream_reset(os); os->serialno=serialno; return(0); }
static int _process_packet(OggVorbis_File *vf,int readp){ ogg_page og; /* handle one packet. Try to fetch it from current stream state */ /* extract packets from page */ while(1){ /* process a packet if we can. If the machine isn't loaded, neither is a page */ if(vf->ready_state==INITSET){ while(1) { ogg_packet op; int result=ogg_stream_packetout(&vf->os,&op); ogg_int64_t granulepos; if(result==-1)return(OV_HOLE); /* hole in the data. */ if(result>0){ /* got a packet. process it */ granulepos=op.granulepos; if(!vorbis_synthesis(&vf->vb,&op)){ /* lazy check for lazy header handling. The header packets aren't audio, so if/when we submit them, vorbis_synthesis will reject them */ /* suck in the synthesis data and track bitrate */ { int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL); vorbis_synthesis_blockin(&vf->vd,&vf->vb); vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples; vf->bittrack+=op.bytes*8; } /* update the pcm offset. */ if(granulepos!=-1 && !op.e_o_s){ int link=(vf->seekable?vf->current_link:0); int i,samples; /* this packet has a pcm_offset on it (the last packet completed on a page carries the offset) After processing (above), we know the pcm position of the *last* sample ready to be returned. Find the offset of the *first* As an aside, this trick is inaccurate if we begin reading anew right at the last page; the end-of-stream granulepos declares the last frame in the stream, and the last packet of the last page may be a partial frame. So, we need a previous granulepos from an in-sequence page to have a reference point. Thus the !op.e_o_s clause above */ samples=vorbis_synthesis_pcmout(&vf->vd,NULL); granulepos-=samples; for(i=0;i<link;i++) granulepos+=vf->pcmlengths[i]; vf->pcm_offset=granulepos; } return(1); } } else break; } } if(vf->ready_state>=OPENED){ if(!readp)return(0); if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* eof. leave unitialized */ /* bitrate tracking; add the header's bytes here, the body bytes are done by packet above */ vf->bittrack+=og.header_len*8; /* has our decoding just traversed a bitstream boundary? */ if(vf->ready_state==INITSET){ if(vf->current_serialno!=ogg_page_serialno(&og)){ _decode_clear(vf); if(!vf->seekable){ vorbis_info_clear(vf->vi); vorbis_comment_clear(vf->vc); } } } } /* Do we need to load a new machine before submitting the page? */ /* This is different in the seekable and non-seekable cases. In the seekable case, we already have all the header information loaded and cached; we just initialize the machine with it and continue on our merry way. In the non-seekable (streaming) case, we'll only be at a boundary if we just left the previous logical bitstream and we're now nominally at the header of the next bitstream */ if(vf->ready_state!=INITSET){ int link; if(vf->ready_state<STREAMSET){ if(vf->seekable){ vf->current_serialno=ogg_page_serialno(&og); /* match the serialno to bitstream section. We use this rather than offset positions to avoid problems near logical bitstream boundaries */ for(link=0;link<vf->links;link++) if(vf->serialnos[link]==vf->current_serialno)break; if(link==vf->links)return(OV_EBADLINK); /* sign of a bogus stream. error out, leave machine uninitialized */ vf->current_link=link; ogg_stream_init(&vf->os,vf->current_serialno); ogg_stream_reset(&vf->os); vf->ready_state=STREAMSET; }else{ /* we're streaming */ /* fetch the three header packets, build the info struct */ int ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og); if(ret)return(ret); vf->current_link++; link=0; } } _make_decode_ready(vf); } ogg_stream_pagein(&vf->os,&og); } }