diff options
author | Michiel Van Der Kolk <not.valid@email.address> | 2005-07-11 15:42:37 +0000 |
---|---|---|
committer | Michiel Van Der Kolk <not.valid@email.address> | 2005-07-11 15:42:37 +0000 |
commit | 9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e (patch) | |
tree | 4c304cd4151020bd5494d279ee68a105ae3a5a3a /songdbj/org/tritonus/lowlevel/pogg/SyncState.java | |
parent | dfa8ecbe609ca8ea194d08560a44fb9a92e94b4b (diff) | |
download | rockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.tar.gz rockbox-9fee0ec4ca0c5b7a334cc29dbb58e76c7a4c736e.zip |
Songdb java version, source. only 1.5 compatible
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7101 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'songdbj/org/tritonus/lowlevel/pogg/SyncState.java')
-rw-r--r-- | songdbj/org/tritonus/lowlevel/pogg/SyncState.java | 339 |
1 files changed, 339 insertions, 0 deletions
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 @@ | |||
1 | /* | ||
2 | * SyncState.java | ||
3 | * | ||
4 | * This file is part of Tritonus: http://www.tritonus.org/ | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Copyright (c) 2000 - 2005 by Matthias Pfisterer | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU Library General Public License as published | ||
12 | * by the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU Library General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Library General Public | ||
21 | * License along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | |<--- this code is formatted to fit into 80 columns --->| | ||
27 | */ | ||
28 | |||
29 | package org.tritonus.lowlevel.pogg; | ||
30 | |||
31 | import org.tritonus.share.TDebug; | ||
32 | |||
33 | |||
34 | /** Wrapper for ogg_sync_state. | ||
35 | */ | ||
36 | public class SyncState | ||
37 | { | ||
38 | /** The stream buffer. | ||
39 | This points to a buffer that holds the incoming data from a stream | ||
40 | until the data is emitted in form of a page. | ||
41 | */ | ||
42 | private byte[] m_abData; | ||
43 | |||
44 | /** The number of bytes in the stream buffer that are used. This | ||
45 | always counts from the beginning of the buffer. So | ||
46 | m_abData[m_nFill] is the first free byte in the buffer. | ||
47 | */ | ||
48 | private int m_nFill; | ||
49 | |||
50 | /** Number of bytes that have been used to construct a returned | ||
51 | page. This is counted from the beginning of the | ||
52 | buffer. m_abData[m_nReturned] is the first valid byte in the | ||
53 | buffer. | ||
54 | */ | ||
55 | private int m_nReturned; | ||
56 | |||
57 | /** | ||
58 | */ | ||
59 | private boolean m_bUnsynced; | ||
60 | |||
61 | /** | ||
62 | */ | ||
63 | private int m_nHeaderBytes; | ||
64 | |||
65 | /** | ||
66 | */ | ||
67 | private int m_nBodyBytes; | ||
68 | |||
69 | /** Page object for re-calculating the checksum. | ||
70 | */ | ||
71 | private Page m_tmpPage; | ||
72 | |||
73 | /** Storage for the checksum saved from the page. | ||
74 | */ | ||
75 | private byte[] m_abChecksum; | ||
76 | |||
77 | |||
78 | public SyncState() | ||
79 | { | ||
80 | if (TDebug.TraceOggNative) { TDebug.out("SyncState.<init>(): begin"); } | ||
81 | m_tmpPage = new Page(); | ||
82 | m_abChecksum = new byte[4]; | ||
83 | if (TDebug.TraceOggNative) { TDebug.out("SyncState.<init>(): end"); } | ||
84 | } | ||
85 | |||
86 | |||
87 | // TODO: remove calls to this method | ||
88 | public void free() | ||
89 | { | ||
90 | } | ||
91 | |||
92 | |||
93 | |||
94 | /** Calls ogg_sync_init(). | ||
95 | */ | ||
96 | public void init() | ||
97 | { | ||
98 | m_abData = null; | ||
99 | m_nFill = 0; | ||
100 | m_nReturned = 0; | ||
101 | m_bUnsynced = false; | ||
102 | m_nHeaderBytes = 0; | ||
103 | m_nBodyBytes = 0; | ||
104 | } | ||
105 | |||
106 | |||
107 | /** Calls ogg_sync_clear(). | ||
108 | */ | ||
109 | public void clear() | ||
110 | { | ||
111 | init(); | ||
112 | } | ||
113 | |||
114 | |||
115 | /** Calls ogg_sync_reset(). | ||
116 | */ | ||
117 | public void reset() | ||
118 | { | ||
119 | m_nFill = 0; | ||
120 | m_nReturned = 0; | ||
121 | m_bUnsynced = false; | ||
122 | m_nHeaderBytes = 0; | ||
123 | m_nBodyBytes = 0; | ||
124 | } | ||
125 | |||
126 | |||
127 | /** Writes to the stream buffer. | ||
128 | */ | ||
129 | public int write(byte[] abBuffer, int nBytes) | ||
130 | { | ||
131 | /* Clear out space that has been previously returned. */ | ||
132 | if (m_nReturned > 0) | ||
133 | { | ||
134 | m_nFill -= m_nReturned; | ||
135 | if (m_nFill > 0) | ||
136 | { | ||
137 | System.arraycopy(m_abData, m_nReturned, | ||
138 | m_abData, 0, | ||
139 | m_nFill); | ||
140 | } | ||
141 | m_nReturned = 0; | ||
142 | } | ||
143 | |||
144 | /* Check for enough space in the stream buffer and if it is | ||
145 | * allocated at all. If there isn't sufficient space, extend | ||
146 | * the buffer. */ | ||
147 | if (m_abData == null || nBytes > m_abData.length - m_nFill) | ||
148 | { | ||
149 | int nNewSize = nBytes + m_nFill + 4096; | ||
150 | byte[] abOldBuffer = m_abData; | ||
151 | m_abData = new byte[nNewSize]; | ||
152 | if (abOldBuffer != null) | ||
153 | { | ||
154 | System.arraycopy(abOldBuffer, 0, m_abData, 0, m_nFill); | ||
155 | } | ||
156 | } | ||
157 | |||
158 | /* Now finally fill with the new data. */ | ||
159 | System.arraycopy(abBuffer, 0, m_abData, m_nFill, nBytes); | ||
160 | m_nFill += nBytes; | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | |||
165 | /** Synchronizes the stream. This method looks if there is a | ||
166 | complete, valid page in the stream buffer. If a page is found, | ||
167 | it is returned in the passed Page object. | ||
168 | |||
169 | @param page The Page to store the result of the page search | ||
170 | in. The content is only changed if the return value is > 0. | ||
171 | |||
172 | @return if a page has been found at the current location, the | ||
173 | length of the page in bytes is returned. If not enough data | ||
174 | for a page is available in the stream buffer, 0 is | ||
175 | returned. If data in the stream buffer has been skipped | ||
176 | because there is no page at the current position, the skip | ||
177 | amount in bytes is returned as a negative number. | ||
178 | */ | ||
179 | public int pageseek(Page page) | ||
180 | { | ||
181 | int nPage = m_nReturned; | ||
182 | int nBytes = m_nFill - m_nReturned; | ||
183 | |||
184 | if (m_nHeaderBytes == 0) | ||
185 | { | ||
186 | if (nBytes < 27) | ||
187 | { | ||
188 | /* Not enough data for a header. */ | ||
189 | return 0; | ||
190 | } | ||
191 | /* Verify capture pattern. */ | ||
192 | if (m_abData[nPage] != (byte) 'O' || | ||
193 | m_abData[nPage + 1] != (byte) 'g' || | ||
194 | m_abData[nPage + 2] != (byte) 'g' || | ||
195 | m_abData[nPage + 3] != (byte) 'S') | ||
196 | { | ||
197 | TDebug.out("wrong capture pattern"); | ||
198 | return syncFailure(); | ||
199 | } | ||
200 | int nHeaderBytes = (m_abData[nPage + 26] & 0xFF) + 27; | ||
201 | if (nBytes < nHeaderBytes) | ||
202 | { | ||
203 | /* Not enough data for header + segment table. */ | ||
204 | return 0; | ||
205 | } | ||
206 | /* Count up body length in the segment table. */ | ||
207 | for (int i = 0; i < (m_abData[nPage + 26] & 0xFF); i++) | ||
208 | { | ||
209 | m_nBodyBytes += (m_abData[nPage + 27 + i] & 0xFF); | ||
210 | } | ||
211 | m_nHeaderBytes = nHeaderBytes; | ||
212 | } | ||
213 | |||
214 | if (m_nBodyBytes + m_nHeaderBytes > nBytes) | ||
215 | { | ||
216 | /* Not enough data for the whole packet. */ | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | /* Save the original checksum, set it to zero and recalculate it. */ | ||
221 | System.arraycopy(m_abData, nPage + 22, m_abChecksum, 0, 4); | ||
222 | m_abData[nPage + 22] = 0; | ||
223 | m_abData[nPage + 23] = 0; | ||
224 | m_abData[nPage + 24] = 0; | ||
225 | m_abData[nPage + 25] = 0; | ||
226 | |||
227 | m_tmpPage.setData(m_abData, nPage, m_nHeaderBytes, | ||
228 | m_abData, nPage + m_nHeaderBytes, m_nBodyBytes); | ||
229 | // TDebug.out("temporary page:"); | ||
230 | // byte[] abHeader = m_tmpPage.getHeader(); | ||
231 | // TDebug.out("H0:" + m_abData[nPage + 0] + " - " + abHeader[0]); | ||
232 | // TDebug.out("H1:" + m_abData[nPage + 1] + " - " + abHeader[1]); | ||
233 | // TDebug.out("H2:" + m_abData[nPage + 2] + " - " + abHeader[2]); | ||
234 | // TDebug.out("H3:" + m_abData[nPage + 3] + " - " + abHeader[3]); | ||
235 | // TDebug.out("" + m_abChecksum[0] + " - " + abHeader[22]); | ||
236 | // TDebug.out("" + m_abChecksum[1] + " - " + abHeader[23]); | ||
237 | // TDebug.out("" + m_abChecksum[2] + " - " + abHeader[24]); | ||
238 | // TDebug.out("" + m_abChecksum[3] + " - " + abHeader[25]); | ||
239 | m_tmpPage.setChecksum(); | ||
240 | byte[] abHeader = m_tmpPage.getHeader(); | ||
241 | //m_tmpPage.free(); | ||
242 | if (abHeader[22] != m_abChecksum[0] || | ||
243 | abHeader[23] != m_abChecksum[1] || | ||
244 | abHeader[24] != m_abChecksum[2] || | ||
245 | abHeader[25] != m_abChecksum[3]) | ||
246 | { | ||
247 | TDebug.out("wrong checksum"); | ||
248 | TDebug.out("" + m_abChecksum[0] + " - " + abHeader[22]); | ||
249 | TDebug.out("" + m_abChecksum[1] + " - " + abHeader[23]); | ||
250 | TDebug.out("" + m_abChecksum[2] + " - " + abHeader[24]); | ||
251 | TDebug.out("" + m_abChecksum[3] + " - " + abHeader[25]); | ||
252 | /* Copy back the saved checksum. */ | ||
253 | System.arraycopy(m_abChecksum, 0, m_abData, nPage + 22, 4); | ||
254 | return syncFailure(); | ||
255 | } | ||
256 | |||
257 | /* Ok, we have a correct page to emit. */ | ||
258 | page.setData(m_abData, nPage, m_nHeaderBytes, | ||
259 | m_abData, nPage + m_nHeaderBytes, m_nBodyBytes); | ||
260 | m_bUnsynced = false; | ||
261 | nBytes = m_nHeaderBytes + m_nBodyBytes; | ||
262 | m_nReturned += nBytes; | ||
263 | m_nHeaderBytes = 0; | ||
264 | m_nBodyBytes = 0; | ||
265 | return nBytes; | ||
266 | } | ||
267 | |||
268 | |||
269 | /** Auxiliary method for pageseek(). | ||
270 | */ | ||
271 | private int syncFailure() | ||
272 | { | ||
273 | int nPage = m_nReturned; | ||
274 | int nBytes = m_nFill - m_nReturned; | ||
275 | m_nHeaderBytes = 0; | ||
276 | m_nBodyBytes = 0; | ||
277 | int nNext = -1; | ||
278 | for (int i = 0; i < nBytes - 1; i++) | ||
279 | { | ||
280 | if (m_abData[nPage + 1 + i] == (byte) 'O') | ||
281 | { | ||
282 | nNext = nPage + 1 + i; | ||
283 | break; | ||
284 | } | ||
285 | } | ||
286 | if (nNext == -1) | ||
287 | { | ||
288 | nNext = m_nFill; | ||
289 | } | ||
290 | m_nReturned = nNext; | ||
291 | return -(nNext - nPage); | ||
292 | } | ||
293 | |||
294 | |||
295 | |||
296 | |||
297 | /** Returns a page from the stream buffer, if possible. This | ||
298 | method searches the current data in the stream buffer for the | ||
299 | beginning of a page. If there is one, it is returned in the | ||
300 | passed Page object. A synchronization error is signaled by a | ||
301 | return value of -1. However, only the first synchronization | ||
302 | error is reported. Consecutive sync errors are suppressed. | ||
303 | |||
304 | @param page The Page to store the result of the page search | ||
305 | in. The content is only changed if the return value is 1. | ||
306 | |||
307 | @return 1 if a page has been found, 0 if there is not enough | ||
308 | data, -1 if a synchronization error occured. | ||
309 | */ | ||
310 | public int pageOut(Page page) | ||
311 | { | ||
312 | while (true) | ||
313 | { | ||
314 | int nReturn = pageseek(page); | ||
315 | if (nReturn > 0) | ||
316 | { | ||
317 | return 1; | ||
318 | } | ||
319 | else if (nReturn == 0) | ||
320 | { | ||
321 | return 0; | ||
322 | } | ||
323 | else // nReturn < 0 | ||
324 | { | ||
325 | if (! m_bUnsynced) | ||
326 | { | ||
327 | m_bUnsynced = true; | ||
328 | return -1; | ||
329 | } | ||
330 | } | ||
331 | } | ||
332 | } | ||
333 | } | ||
334 | |||
335 | |||
336 | |||
337 | |||
338 | |||
339 | /*** SyncState.java ***/ | ||