From 9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e Mon Sep 17 00:00:00 2001 From: Michiel Van Der Kolk Date: Mon, 11 Jul 2005 15:42:37 +0000 Subject: Songdb java version, source. only 1.5 compatible git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7101 a1c6a512-1295-4272-9138-f99709370657 --- songdbj/org/tritonus/lowlevel/pogg/SyncState.java | 339 ++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 songdbj/org/tritonus/lowlevel/pogg/SyncState.java (limited to 'songdbj/org/tritonus/lowlevel/pogg/SyncState.java') diff --git a/songdbj/org/tritonus/lowlevel/pogg/SyncState.java b/songdbj/org/tritonus/lowlevel/pogg/SyncState.java new file mode 100644 index 0000000000..4246808bd3 --- /dev/null +++ b/songdbj/org/tritonus/lowlevel/pogg/SyncState.java @@ -0,0 +1,339 @@ +/* + * SyncState.java + * + * This file is part of Tritonus: http://www.tritonus.org/ + */ + +/* + * Copyright (c) 2000 - 2005 by Matthias Pfisterer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* +|<--- this code is formatted to fit into 80 columns --->| +*/ + +package org.tritonus.lowlevel.pogg; + +import org.tritonus.share.TDebug; + + +/** Wrapper for ogg_sync_state. + */ +public class SyncState +{ + /** The stream buffer. + This points to a buffer that holds the incoming data from a stream + until the data is emitted in form of a page. + */ + private byte[] m_abData; + + /** The number of bytes in the stream buffer that are used. This + always counts from the beginning of the buffer. So + m_abData[m_nFill] is the first free byte in the buffer. + */ + private int m_nFill; + + /** Number of bytes that have been used to construct a returned + page. This is counted from the beginning of the + buffer. m_abData[m_nReturned] is the first valid byte in the + buffer. + */ + private int m_nReturned; + + /** + */ + private boolean m_bUnsynced; + + /** + */ + private int m_nHeaderBytes; + + /** + */ + private int m_nBodyBytes; + + /** Page object for re-calculating the checksum. + */ + private Page m_tmpPage; + + /** Storage for the checksum saved from the page. + */ + private byte[] m_abChecksum; + + + public SyncState() + { + if (TDebug.TraceOggNative) { TDebug.out("SyncState.(): begin"); } + m_tmpPage = new Page(); + m_abChecksum = new byte[4]; + if (TDebug.TraceOggNative) { TDebug.out("SyncState.(): end"); } + } + + + // TODO: remove calls to this method + public void free() + { + } + + + + /** Calls ogg_sync_init(). + */ + public void init() + { + m_abData = null; + m_nFill = 0; + m_nReturned = 0; + m_bUnsynced = false; + m_nHeaderBytes = 0; + m_nBodyBytes = 0; + } + + + /** Calls ogg_sync_clear(). + */ + public void clear() + { + init(); + } + + + /** Calls ogg_sync_reset(). + */ + public void reset() + { + m_nFill = 0; + m_nReturned = 0; + m_bUnsynced = false; + m_nHeaderBytes = 0; + m_nBodyBytes = 0; + } + + + /** Writes to the stream buffer. + */ + public int write(byte[] abBuffer, int nBytes) + { + /* Clear out space that has been previously returned. */ + if (m_nReturned > 0) + { + m_nFill -= m_nReturned; + if (m_nFill > 0) + { + System.arraycopy(m_abData, m_nReturned, + m_abData, 0, + m_nFill); + } + m_nReturned = 0; + } + + /* Check for enough space in the stream buffer and if it is + * allocated at all. If there isn't sufficient space, extend + * the buffer. */ + if (m_abData == null || nBytes > m_abData.length - m_nFill) + { + int nNewSize = nBytes + m_nFill + 4096; + byte[] abOldBuffer = m_abData; + m_abData = new byte[nNewSize]; + if (abOldBuffer != null) + { + System.arraycopy(abOldBuffer, 0, m_abData, 0, m_nFill); + } + } + + /* Now finally fill with the new data. */ + System.arraycopy(abBuffer, 0, m_abData, m_nFill, nBytes); + m_nFill += nBytes; + return 0; + } + + + /** Synchronizes the stream. This method looks if there is a + complete, valid page in the stream buffer. If a page is found, + it is returned in the passed Page object. + + @param page The Page to store the result of the page search + in. The content is only changed if the return value is > 0. + + @return if a page has been found at the current location, the + length of the page in bytes is returned. If not enough data + for a page is available in the stream buffer, 0 is + returned. If data in the stream buffer has been skipped + because there is no page at the current position, the skip + amount in bytes is returned as a negative number. + */ + public int pageseek(Page page) + { + int nPage = m_nReturned; + int nBytes = m_nFill - m_nReturned; + + if (m_nHeaderBytes == 0) + { + if (nBytes < 27) + { + /* Not enough data for a header. */ + return 0; + } + /* Verify capture pattern. */ + if (m_abData[nPage] != (byte) 'O' || + m_abData[nPage + 1] != (byte) 'g' || + m_abData[nPage + 2] != (byte) 'g' || + m_abData[nPage + 3] != (byte) 'S') + { + TDebug.out("wrong capture pattern"); + return syncFailure(); + } + int nHeaderBytes = (m_abData[nPage + 26] & 0xFF) + 27; + if (nBytes < nHeaderBytes) + { + /* Not enough data for header + segment table. */ + return 0; + } + /* Count up body length in the segment table. */ + for (int i = 0; i < (m_abData[nPage + 26] & 0xFF); i++) + { + m_nBodyBytes += (m_abData[nPage + 27 + i] & 0xFF); + } + m_nHeaderBytes = nHeaderBytes; + } + + if (m_nBodyBytes + m_nHeaderBytes > nBytes) + { + /* Not enough data for the whole packet. */ + return 0; + } + + /* Save the original checksum, set it to zero and recalculate it. */ + System.arraycopy(m_abData, nPage + 22, m_abChecksum, 0, 4); + m_abData[nPage + 22] = 0; + m_abData[nPage + 23] = 0; + m_abData[nPage + 24] = 0; + m_abData[nPage + 25] = 0; + + m_tmpPage.setData(m_abData, nPage, m_nHeaderBytes, + m_abData, nPage + m_nHeaderBytes, m_nBodyBytes); +// TDebug.out("temporary page:"); +// byte[] abHeader = m_tmpPage.getHeader(); +// TDebug.out("H0:" + m_abData[nPage + 0] + " - " + abHeader[0]); +// TDebug.out("H1:" + m_abData[nPage + 1] + " - " + abHeader[1]); +// TDebug.out("H2:" + m_abData[nPage + 2] + " - " + abHeader[2]); +// TDebug.out("H3:" + m_abData[nPage + 3] + " - " + abHeader[3]); +// TDebug.out("" + m_abChecksum[0] + " - " + abHeader[22]); +// TDebug.out("" + m_abChecksum[1] + " - " + abHeader[23]); +// TDebug.out("" + m_abChecksum[2] + " - " + abHeader[24]); +// TDebug.out("" + m_abChecksum[3] + " - " + abHeader[25]); + m_tmpPage.setChecksum(); + byte[] abHeader = m_tmpPage.getHeader(); + //m_tmpPage.free(); + if (abHeader[22] != m_abChecksum[0] || + abHeader[23] != m_abChecksum[1] || + abHeader[24] != m_abChecksum[2] || + abHeader[25] != m_abChecksum[3]) + { + TDebug.out("wrong checksum"); + TDebug.out("" + m_abChecksum[0] + " - " + abHeader[22]); + TDebug.out("" + m_abChecksum[1] + " - " + abHeader[23]); + TDebug.out("" + m_abChecksum[2] + " - " + abHeader[24]); + TDebug.out("" + m_abChecksum[3] + " - " + abHeader[25]); + /* Copy back the saved checksum. */ + System.arraycopy(m_abChecksum, 0, m_abData, nPage + 22, 4); + return syncFailure(); + } + + /* Ok, we have a correct page to emit. */ + page.setData(m_abData, nPage, m_nHeaderBytes, + m_abData, nPage + m_nHeaderBytes, m_nBodyBytes); + m_bUnsynced = false; + nBytes = m_nHeaderBytes + m_nBodyBytes; + m_nReturned += nBytes; + m_nHeaderBytes = 0; + m_nBodyBytes = 0; + return nBytes; + } + + + /** Auxiliary method for pageseek(). + */ + private int syncFailure() + { + int nPage = m_nReturned; + int nBytes = m_nFill - m_nReturned; + m_nHeaderBytes = 0; + m_nBodyBytes = 0; + int nNext = -1; + for (int i = 0; i < nBytes - 1; i++) + { + if (m_abData[nPage + 1 + i] == (byte) 'O') + { + nNext = nPage + 1 + i; + break; + } + } + if (nNext == -1) + { + nNext = m_nFill; + } + m_nReturned = nNext; + return -(nNext - nPage); + } + + + + + /** Returns a page from the stream buffer, if possible. This + method searches the current data in the stream buffer for the + beginning of a page. If there is one, it is returned in the + passed Page object. A synchronization error is signaled by a + return value of -1. However, only the first synchronization + error is reported. Consecutive sync errors are suppressed. + + @param page The Page to store the result of the page search + in. The content is only changed if the return value is 1. + + @return 1 if a page has been found, 0 if there is not enough + data, -1 if a synchronization error occured. + */ + public int pageOut(Page page) + { + while (true) + { + int nReturn = pageseek(page); + if (nReturn > 0) + { + return 1; + } + else if (nReturn == 0) + { + return 0; + } + else // nReturn < 0 + { + if (! m_bUnsynced) + { + m_bUnsynced = true; + return -1; + } + } + } + } +} + + + + + +/*** SyncState.java ***/ -- cgit v1.2.3