Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@oneman
Created March 21, 2012 09:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oneman/2145713 to your computer and use it in GitHub Desktop.
Save oneman/2145713 to your computer and use it in GitHub Desktop.
New Ogg Vorbis chaining kludge, works, no audio glitch, but if you seek, you will surely seg
diff --git a/content/media/ogg/nsOggReader.cpp b/content/media/ogg/nsOggReader.cpp
index 7575e08..e61e6da 100644
--- a/content/media/ogg/nsOggReader.cpp
+++ b/content/media/ogg/nsOggReader.cpp
@@ -108,7 +108,8 @@ nsOggReader::nsOggReader(nsBuiltinDecoder* aDecoder)
mSkeletonState(nsnull),
mVorbisSerial(0),
mTheoraSerial(0),
- mPageOffset(0)
+ mPageOffset(0),
+ mChainKludgeState(0)
{
MOZ_COUNT_CTOR(nsOggReader);
memset(&mTheoraInfo, 0, sizeof(mTheoraInfo));
@@ -410,8 +411,13 @@ bool nsOggReader::DecodeAudioData()
// We've encountered an end of bitstream packet, or we've hit the end of
// file while trying to decode, so inform the audio queue that there'll
// be no more samples.
- mAudioQueue.Finish();
- return false;
+ if (HasAudio() && !HasVideo()) {
+ mChainKludgeState = 2;
+ printf("End of vorbis logical stream\n");
+ } else {
+ mAudioQueue.Finish();
+ return false;
+ }
}
return true;
@@ -580,9 +586,28 @@ ogg_packet* nsOggReader::NextOggPacket(nsOggCodecState* aCodecState)
ogg_packet* packet;
while ((packet = aCodecState->PacketOut()) == nsnull) {
+
+ ogg_page page;
+ while (mChainKludgeState) {
+ if (ReadOggPage(&page) == -1) {
+ return nsnull;
+ }
+ if (mChainKludgeState == 2) {
+ nsOggCodecState* orig_codecState = nsnull;
+ //PRUint32 old_serial = mVorbisSerial;
+ mCodecStates.Get(mVorbisSerial, &orig_codecState);
+ mVorbisSerial = ogg_page_serialno(&page);
+ mCodecStates.Put(mVorbisSerial, orig_codecState);
+ //mCodecStates.Remove(old_serial);
+ mVorbisState->mSerial = mVorbisSerial;
+ mKnownStreams.AppendElement(mVorbisSerial);
+ ogg_stream_reset_serialno(&mVorbisState->mState, mVorbisState->mSerial);
+ vorbis_synthesis_restart(&mVorbisState->mDsp);
+ }
+ mChainKludgeState--;
+ }
// The codec state does not have any buffered pages, so try to read another
// page from the channel.
- ogg_page page;
if (ReadOggPage(&page) == -1) {
return nsnull;
}
diff --git a/content/media/ogg/nsOggReader.h b/content/media/ogg/nsOggReader.h
index 54302b3..b79d311 100644
--- a/content/media/ogg/nsOggReader.h
+++ b/content/media/ogg/nsOggReader.h
@@ -218,8 +218,8 @@ private:
// Decodes a packet of Theora data, and inserts its frame into the
// video queue. May return NS_ERROR_OUT_OF_MEMORY. Caller must have obtained
- // the reader's monitor. aTimeThreshold is the current playback position
- // in media time in microseconds. Frames with an end time before this will
+ // the reader's monitor. aTimeThreshold is the current playback position
+ // in media time in microseconds. Frames with an end time before this will
// not be enqueued.
nsresult DecodeTheora(ogg_packet* aPacket, PRInt64 aTimeThreshold);
@@ -259,6 +259,7 @@ private:
// Ogg decoding state.
ogg_sync_state mOggState;
+ int mChainKludgeState;
// Vorbis/Theora data used to compute timestamps. This is written on the
// decoder thread and read on the main thread. All reading on the main
// thread must be done after metadataloaded. We can't use the existing
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment