Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
89ce1cce
authored
Jan 22, 2016
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
OggVorbisExtractor (WIP - Seeking not yet enabled)
parent
88fa1495
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
3366 additions
and
0 deletions
demo/src/main/java/com/google/android/exoplayer/demo/Samples.java
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/OggReaderTest.java
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/OggVorbisExtractorTest.java
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/RecordableExtractorInput.java
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/RecordableOggExtractorInput.java
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/TestData.java
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/VorbisBitArrayTest.java
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/VorbisUtilTest.java
library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java
library/src/main/java/com/google/android/exoplayer/extractor/ogg/OggReader.java
library/src/main/java/com/google/android/exoplayer/extractor/ogg/OggVorbisExtractor.java
library/src/main/java/com/google/android/exoplayer/extractor/ogg/VorbisBitArray.java
library/src/main/java/com/google/android/exoplayer/extractor/ogg/VorbisUtil.java
demo/src/main/java/com/google/android/exoplayer/demo/Samples.java
View file @
89ce1cce
...
...
@@ -242,6 +242,8 @@ import java.util.Locale;
+
"&key=ik0"
,
Util
.
TYPE_OTHER
),
new
Sample
(
"Google Play (MP3 Audio)"
,
"http://storage.googleapis.com/exoplayer-test-media-0/play.mp3"
,
Util
.
TYPE_OTHER
),
new
Sample
(
"Google Play (Ogg/Vorbis Audio)"
,
"https://storage.googleapis.com/exoplayer-test-media-1/ogg/play.ogg"
,
Util
.
TYPE_OTHER
),
new
Sample
(
"Google Glass (WebM Video with Vorbis Audio)"
,
"http://demos.webmproject.org/exoplayer/glass_vp9_vorbis.webm"
,
Util
.
TYPE_OTHER
),
new
Sample
(
"Big Buck Bunny (FLV Video)"
,
...
...
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/OggReaderTest.java
0 → 100644
View file @
89ce1cce
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer
.
extractor
.
ogg
;
import
com.google.android.exoplayer.util.ParsableByteArray
;
import
android.util.Log
;
import
junit.framework.TestCase
;
import
java.io.IOException
;
/**
* Unit test for {@link OggReader}
*/
public
final
class
OggReaderTest
extends
TestCase
{
private
static
final
String
TAG
=
"OggReaderTest"
;
private
OggReader
oggReader
;
private
RecordableOggExtractorInput
extractorInput
;
@Override
public
void
setUp
()
throws
Exception
{
super
.
setUp
();
extractorInput
=
new
RecordableOggExtractorInput
(
1024
*
64
);
// we want the mocked ExtractorInput to throw errors often
extractorInput
.
doThrowExceptionsAtPeek
(
true
);
extractorInput
.
doThrowExceptionsAtRead
(
true
);
// create reader
oggReader
=
new
OggReader
();
oggReader
.
reset
();
}
public
void
testReadPacketUntilEOFIncludingAnEmptyPage
()
throws
Exception
{
// record first page with a single packet
extractorInput
.
recordOggHeader
((
byte
)
0x02
,
0
,
(
byte
)
0x01
);
extractorInput
.
recordOggLaces
(
new
byte
[]{
0x08
});
extractorInput
.
recordOggPacket
(
RecordableExtractorInput
.
getBytesGrowingValues
(
8
));
// record intermediate page with two packets
extractorInput
.
recordOggHeader
((
byte
)
0x00
,
16
,
(
byte
)
0x02
);
extractorInput
.
recordOggLaces
(
new
byte
[]{(
byte
)
0xFF
,
0x11
});
extractorInput
.
recordOggPacket
(
RecordableExtractorInput
.
getBytesGrowingValues
(
255
+
17
));
// empty page
extractorInput
.
recordOggHeader
((
byte
)
0x00
,
16
,
(
byte
)
0x00
);
// record last page with two packets (256 and 271 bytes)
extractorInput
.
recordOggHeader
((
byte
)
0x04
,
128
,
(
byte
)
0x04
);
extractorInput
.
recordOggLaces
(
new
byte
[]{(
byte
)
0xFF
,
0x01
,
(
byte
)
0xff
,
0x10
});
extractorInput
.
recordOggPacket
(
RecordableExtractorInput
.
getBytesGrowingValues
(
255
+
1
+
255
+
16
));
// read first packet
final
ParsableByteArray
packetArray
=
new
ParsableByteArray
(
new
byte
[
255
*
255
],
0
);
readPacketUntilSuccess
(
packetArray
);
// verify
assertEquals
(
8
,
packetArray
.
limit
());
assertTrue
((
oggReader
.
getPageHeader
().
type
&
0x02
)
==
0x02
);
assertFalse
((
oggReader
.
getPageHeader
().
type
&
0x04
)
==
0x04
);
assertEquals
(
0x02
,
oggReader
.
getPageHeader
().
type
);
assertEquals
(
27
+
1
,
oggReader
.
getPageHeader
().
headerSize
);
assertEquals
(
8
,
oggReader
.
getPageHeader
().
bodySize
);
assertEquals
(
RecordableExtractorInput
.
STREAM_REVISION
,
oggReader
.
getPageHeader
().
revision
);
assertEquals
(
1
,
oggReader
.
getPageHeader
().
pageSegmentCount
);
assertEquals
(
1000
,
oggReader
.
getPageHeader
().
pageSequenceNumber
);
assertEquals
(
4096
,
oggReader
.
getPageHeader
().
streamSerialNumber
);
assertEquals
(
0
,
oggReader
.
getPageHeader
().
granulePosition
);
for
(
int
i
=
0
;
i
<
8
;
i
++)
{
assertEquals
(
i
,
packetArray
.
readUnsignedByte
());
}
packetArray
.
reset
();
// read second packet
readPacketUntilSuccess
(
packetArray
);
// verify
assertEquals
(
255
+
17
,
packetArray
.
limit
());
assertFalse
((
oggReader
.
getPageHeader
().
type
&
0x02
)
==
0x02
);
assertFalse
((
oggReader
.
getPageHeader
().
type
&
0x04
)
==
0x04
);
assertEquals
(
0
,
oggReader
.
getPageHeader
().
type
);
assertEquals
(
27
+
2
,
oggReader
.
getPageHeader
().
headerSize
);
assertEquals
(
255
+
17
,
oggReader
.
getPageHeader
().
bodySize
);
assertEquals
(
2
,
oggReader
.
getPageHeader
().
pageSegmentCount
);
assertEquals
(
1001
,
oggReader
.
getPageHeader
().
pageSequenceNumber
);
assertEquals
(
16
,
oggReader
.
getPageHeader
().
granulePosition
);
packetArray
.
reset
();
// read next packet and skip empty page
readPacketUntilSuccess
(
packetArray
);
// verify
assertEquals
(
255
+
1
,
packetArray
.
limit
());
assertFalse
((
oggReader
.
getPageHeader
().
type
&
0x02
)
==
0x02
);
assertTrue
((
oggReader
.
getPageHeader
().
type
&
0x04
)
==
0x04
);
assertEquals
(
4
,
oggReader
.
getPageHeader
().
type
);
assertEquals
(
27
+
4
,
oggReader
.
getPageHeader
().
headerSize
);
assertEquals
(
255
+
1
+
255
+
16
,
oggReader
.
getPageHeader
().
bodySize
);
assertEquals
(
4
,
oggReader
.
getPageHeader
().
pageSegmentCount
);
// page 1002 is empty, so current is 1003
assertEquals
(
1003
,
oggReader
.
getPageHeader
().
pageSequenceNumber
);
assertEquals
(
128
,
oggReader
.
getPageHeader
().
granulePosition
);
packetArray
.
reset
();
// read last packet
readPacketUntilSuccess
(
packetArray
);
assertEquals
(
255
+
16
,
packetArray
.
limit
());
// EOF!
readEOFUntilSuccess
(
packetArray
,
10
);
}
public
void
testReadPacketWithZeroSizeTerminator
()
throws
Exception
{
// record first page with a single packet
extractorInput
.
recordOggHeader
((
byte
)
0x06
,
0
,
(
byte
)
0x04
);
extractorInput
.
recordOggLaces
(
new
byte
[]{(
byte
)
0xff
,
0x00
,
0x00
,
0x08
});
extractorInput
.
recordOggPacket
(
RecordableExtractorInput
.
getBytesGrowingValues
(
255
+
8
));
ParsableByteArray
packetArray
=
new
ParsableByteArray
(
new
byte
[
255
*
255
],
0
);
readPacketUntilSuccess
(
packetArray
);
assertEquals
(
255
,
packetArray
.
limit
());
packetArray
.
reset
();
readPacketUntilSuccess
(
packetArray
);
assertEquals
(
8
,
packetArray
.
limit
());
readEOFUntilSuccess
(
packetArray
,
10
);
}
public
void
testReadContinuedPacket
()
throws
Exception
{
// record first page with a packet continuing on the second page
extractorInput
.
recordOggHeader
((
byte
)
0x02
,
0
,
(
byte
)
0x02
);
extractorInput
.
recordOggLaces
(
new
byte
[]{(
byte
)
0xFF
,
(
byte
)
0xFF
});
extractorInput
.
recordOggPacket
(
RecordableExtractorInput
.
getBytesGrowingValues
(
510
));
// record the continuing page
extractorInput
.
recordOggHeader
((
byte
)
0x05
,
10
,
(
byte
)
0x01
);
extractorInput
.
recordOggLaces
(
new
byte
[]{
0x08
});
extractorInput
.
recordOggPacket
(
RecordableExtractorInput
.
getBytesGrowingValues
(
8
,
(
byte
)
0x22
));
// there is only one single packet across two pages
ParsableByteArray
packetArray
=
new
ParsableByteArray
(
new
byte
[
255
*
255
],
0
);
readPacketUntilSuccess
(
packetArray
);
assertEquals
(
255
+
255
+
8
,
packetArray
.
limit
());
assertTrue
((
oggReader
.
getPageHeader
().
type
&
0x04
)
==
0x04
);
assertFalse
((
oggReader
.
getPageHeader
().
type
&
0x02
)
==
0x02
);
// we must be on the second page already
assertEquals
(
1001
,
oggReader
.
getPageHeader
().
pageSequenceNumber
);
// verify packet data
for
(
int
i
=
0
;
i
<
255
;
i
++)
{
assertEquals
(
i
,
packetArray
.
readUnsignedByte
());
}
assertEquals
(
255
,
packetArray
.
getPosition
());
for
(
int
i
=
0
;
i
<
255
;
i
++)
{
assertEquals
(
i
,
packetArray
.
readUnsignedByte
());
}
assertEquals
(
510
,
packetArray
.
getPosition
());
for
(
int
i
=
0
;
i
<
8
;
i
++)
{
assertEquals
(
i
+
0x22
,
packetArray
.
readUnsignedByte
());
}
assertEquals
(
0
,
packetArray
.
bytesLeft
());
// EOF!
readEOFUntilSuccess
(
packetArray
,
10
);
}
// no one does this with vorbis buts it's supported
public
void
testReadContinuedPacketOverMoreThan2Pages
()
throws
Exception
{
// record first page with a packet continuing on the second page
extractorInput
.
recordOggHeader
((
byte
)
0x02
,
0
,
(
byte
)
0x02
);
extractorInput
.
recordOggLaces
(
new
byte
[]{(
byte
)
0xFF
,
(
byte
)
0xFF
});
extractorInput
.
recordOggPacket
(
RecordableExtractorInput
.
getBytesGrowingValues
(
510
));
// record the first continuing page
extractorInput
.
recordOggHeader
((
byte
)
0x01
,
10
,
(
byte
)
0x01
);
extractorInput
.
recordOggLaces
(
new
byte
[]{(
byte
)
0xFF
});
extractorInput
.
recordOggPacket
(
RecordableExtractorInput
.
getBytesGrowingValues
(
255
));
// record the second continuing page
extractorInput
.
recordOggHeader
((
byte
)
0x01
,
10
,
(
byte
)
0x01
);
extractorInput
.
recordOggLaces
(
new
byte
[]{(
byte
)
0xFF
});
extractorInput
.
recordOggPacket
(
RecordableExtractorInput
.
getBytesGrowingValues
(
255
));
// record the third continuing page
extractorInput
.
recordOggHeader
((
byte
)
0x05
,
10
,
(
byte
)
0x01
);
extractorInput
.
recordOggLaces
(
new
byte
[]{(
byte
)
0x08
});
extractorInput
.
recordOggPacket
(
RecordableExtractorInput
.
getBytesGrowingValues
(
8
,
(
byte
)
0x22
));
// there is only one single packet across two pages
ParsableByteArray
packetArray
=
new
ParsableByteArray
(
new
byte
[
255
*
255
],
0
);
readPacketUntilSuccess
(
packetArray
);
assertEquals
(
255
+
255
+
255
+
255
+
8
,
packetArray
.
limit
());
assertTrue
((
oggReader
.
getPageHeader
().
type
&
0x04
)
==
0x04
);
assertFalse
((
oggReader
.
getPageHeader
().
type
&
0x02
)
==
0x02
);
// we must be on the fourth page already
assertEquals
(
1003
,
oggReader
.
getPageHeader
().
pageSequenceNumber
);
// verify packet data
for
(
int
i
=
0
;
i
<
255
;
i
++)
{
assertEquals
(
i
,
packetArray
.
readUnsignedByte
());
}
assertEquals
(
255
,
packetArray
.
getPosition
());
for
(
int
i
=
0
;
i
<
255
;
i
++)
{
assertEquals
(
i
,
packetArray
.
readUnsignedByte
());
}
assertEquals
(
510
,
packetArray
.
getPosition
());
for
(
int
i
=
0
;
i
<
255
;
i
++)
{
assertEquals
(
i
,
packetArray
.
readUnsignedByte
());
}
assertEquals
(
765
,
packetArray
.
getPosition
());
for
(
int
i
=
0
;
i
<
255
;
i
++)
{
assertEquals
(
i
,
packetArray
.
readUnsignedByte
());
}
assertEquals
(
1020
,
packetArray
.
getPosition
());
for
(
int
i
=
0
;
i
<
8
;
i
++)
{
assertEquals
(
i
+
0x22
,
packetArray
.
readUnsignedByte
());
}
assertEquals
(
0
,
packetArray
.
bytesLeft
());
// EOF!
readEOFUntilSuccess
(
packetArray
,
10
);
}
public
void
testReadExceptionThrownWhilePeekingHeader
()
throws
Exception
{
// record first page with two packets packet
extractorInput
.
recordOggHeader
((
byte
)
0x02
,
0
,
(
byte
)
0x02
);
extractorInput
.
recordOggLaces
(
new
byte
[]{(
byte
)
0x01
,
(
byte
)
0x08
});
extractorInput
.
recordOggPacket
(
new
byte
[]{
0x10
});
extractorInput
.
recordOggPacket
(
RecordableExtractorInput
.
getBytesGrowingValues
(
8
));
// record next page
extractorInput
.
recordOggHeader
((
byte
)
0x05
,
10
,
(
byte
)
0x01
);
extractorInput
.
recordOggLaces
(
new
byte
[]{
0x08
});
extractorInput
.
recordOggPacket
(
RecordableExtractorInput
.
getBytesGrowingValues
(
8
,
(
byte
)
0x22
));
ParsableByteArray
packetArray
=
new
ParsableByteArray
(
new
byte
[
255
*
255
],
0
);
readPacketUntilSuccess
(
packetArray
);
// verify packet data
assertEquals
(
1
,
packetArray
.
limit
());
assertEquals
(
0x10
,
packetArray
.
data
[
0
]);
// verify header
assertTrue
((
oggReader
.
getPageHeader
().
type
&
0x02
)
==
0x02
);
assertFalse
((
oggReader
.
getPageHeader
().
type
&
0x04
)
==
0x04
);
assertEquals
(
27
+
2
,
oggReader
.
getPageHeader
().
headerSize
);
assertEquals
(
9
,
oggReader
.
getPageHeader
().
bodySize
);
assertEquals
(
2
,
oggReader
.
getPageHeader
().
pageSegmentCount
);
assertEquals
(
1000
,
oggReader
.
getPageHeader
().
pageSequenceNumber
);
assertEquals
(
0
,
oggReader
.
getPageHeader
().
granulePosition
);
packetArray
.
reset
();
readPacketUntilSuccess
(
packetArray
);
}
public
void
testReadNoZeroSizedPacketsAreReturned
()
throws
Exception
{
extractorInput
.
recordOggHeader
((
byte
)
0x02
,
0
,
(
byte
)
0x04
);
extractorInput
.
recordOggLaces
(
new
byte
[]{(
byte
)
0x08
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x08
});
extractorInput
.
recordOggPacket
(
new
byte
[]{
0x10
,
0x10
,
0x10
,
0x10
,
0x10
,
0x10
,
0x10
,
0x10
});
extractorInput
.
recordOggPacket
(
new
byte
[]{
0x20
,
0x20
,
0x20
,
0x20
,
0x20
,
0x20
,
0x20
,
0x20
});
ParsableByteArray
packetArray
=
new
ParsableByteArray
(
new
byte
[
1024
],
0
);
readPacketUntilSuccess
(
packetArray
);
assertEquals
(
8
,
packetArray
.
limit
());
assertEquals
(
0x10
,
packetArray
.
data
[
0
]);
assertEquals
(
0x10
,
packetArray
.
data
[
7
]);
packetArray
.
reset
();
readPacketUntilSuccess
(
packetArray
);
assertEquals
(
8
,
packetArray
.
limit
());
assertEquals
(
0x20
,
packetArray
.
data
[
0
]);
assertEquals
(
0x20
,
packetArray
.
data
[
7
]);
readEOFUntilSuccess
(
packetArray
,
10
);
}
public
void
testReadZeroSizedPacketsAtEndOfStream
()
throws
Exception
{
extractorInput
.
recordOggHeader
((
byte
)
0x02
,
0
,
(
byte
)
0x01
);
extractorInput
.
recordOggLaces
(
new
byte
[]{(
byte
)
0x08
});
extractorInput
.
recordOggPacket
(
new
byte
[]{
0x10
,
0x10
,
0x10
,
0x10
,
0x10
,
0x10
,
0x10
,
0x10
});
extractorInput
.
recordOggHeader
((
byte
)
0x04
,
0
,
(
byte
)
0x03
);
extractorInput
.
recordOggLaces
(
new
byte
[]{(
byte
)
0x08
,
(
byte
)
0x00
,
(
byte
)
0x00
});
extractorInput
.
recordOggPacket
(
new
byte
[]{
0x10
,
0x10
,
0x10
,
0x10
,
0x10
,
0x10
,
0x10
,
0x10
});
extractorInput
.
recordOggHeader
((
byte
)
0x04
,
0
,
(
byte
)
0x03
);
extractorInput
.
recordOggLaces
(
new
byte
[]{(
byte
)
0x08
,
0x00
,
0x00
});
extractorInput
.
recordOggPacket
(
new
byte
[]{
0x10
,
0x10
,
0x10
,
0x10
,
0x10
,
0x10
,
0x10
,
0x10
});
ParsableByteArray
packetArray
=
new
ParsableByteArray
(
new
byte
[
1024
],
0
);
readPacketUntilSuccess
(
packetArray
);
assertEquals
(
8
,
packetArray
.
limit
());
packetArray
.
reset
();
readPacketUntilSuccess
(
packetArray
);
assertEquals
(
8
,
packetArray
.
limit
());
packetArray
.
reset
();
readPacketUntilSuccess
(
packetArray
);
assertEquals
(
8
,
packetArray
.
limit
());
packetArray
.
reset
();
readEOFUntilSuccess
(
packetArray
,
10
);
assertEquals
(
0
,
packetArray
.
limit
());
}
private
void
readPacketUntilSuccess
(
ParsableByteArray
packetArray
)
{
int
exceptionCount
=
0
;
while
(
exceptionCount
<
10
)
{
try
{
assertTrue
(
oggReader
.
readPacket
(
extractorInput
,
packetArray
));
break
;
}
catch
(
IOException
|
InterruptedException
e
)
{
exceptionCount
++;
extractorInput
.
resetPeekPosition
();
}
}
if
(
exceptionCount
==
10
)
{
fail
(
"maxException threshold reached"
);
}
}
private
void
readEOFUntilSuccess
(
ParsableByteArray
packetArray
,
int
maxExceptions
)
{
int
exceptionCount
=
0
;
while
(
exceptionCount
<
maxExceptions
)
{
try
{
assertFalse
(
oggReader
.
readPacket
(
extractorInput
,
packetArray
));
break
;
}
catch
(
IOException
|
InterruptedException
e
)
{
exceptionCount
++;
Log
.
e
(
TAG
,
e
.
getMessage
(),
e
);
}
}
if
(
exceptionCount
==
maxExceptions
)
{
fail
(
"maxException threshold reached"
);
}
}
}
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/OggVorbisExtractorTest.java
0 → 100644
View file @
89ce1cce
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer
.
extractor
.
ogg
;
import
com.google.android.exoplayer.util.ParsableByteArray
;
import
android.util.Log
;
import
junit.framework.TestCase
;
import
java.io.IOException
;
/**
* Unit test for {@link OggVorbisExtractor}.
*/
public
final
class
OggVorbisExtractorTest
extends
TestCase
{
private
static
final
String
TAG
=
"OggVorbisExtractorTest"
;
private
OggVorbisExtractor
extractor
;
private
RecordableOggExtractorInput
extractorInput
;
@Override
public
void
setUp
()
throws
Exception
{
super
.
setUp
();
extractorInput
=
new
RecordableOggExtractorInput
(
1024
*
64
);
extractor
=
new
OggVorbisExtractor
();
}
public
void
testSniff
()
throws
Exception
{
extractorInput
.
recordOggHeader
((
byte
)
0x02
,
0
,
(
byte
)
0x02
);
extractorInput
.
recordOggLaces
(
new
byte
[]{
120
,
120
});
assertTrue
(
extractor
.
sniff
(
extractorInput
));
}
public
void
testSniffFails
()
throws
Exception
{
extractorInput
.
recordOggHeader
((
byte
)
0x00
,
0
,
(
byte
)
0
);
assertFalse
(
extractor
.
sniff
(
extractorInput
));
}
public
void
testAppendNumberOfSamples
()
throws
Exception
{
ParsableByteArray
buffer
=
new
ParsableByteArray
(
4
);
buffer
.
setLimit
(
0
);
OggVorbisExtractor
.
appendNumberOfSamples
(
buffer
,
0x01234567
);
assertEquals
(
4
,
buffer
.
limit
());
assertEquals
(
0x67
,
buffer
.
data
[
0
]);
assertEquals
(
0x45
,
buffer
.
data
[
1
]);
assertEquals
(
0x23
,
buffer
.
data
[
2
]);
assertEquals
(
0x01
,
buffer
.
data
[
3
]);
}
public
void
testReadSetupHeadersWithIOExceptions
()
throws
IOException
,
InterruptedException
{
extractorInput
.
doThrowExceptionsAtRead
(
true
);
extractorInput
.
doThrowExceptionsAtPeek
(
true
);
byte
[]
data
=
TestData
.
getVorbisHeaderPages
();
extractorInput
.
record
(
data
);
int
exceptionCount
=
0
;
int
maxExceptions
=
20
;
OggVorbisExtractor
.
VorbisSetup
vorbisSetup
;
while
(
exceptionCount
<
maxExceptions
)
{
try
{
vorbisSetup
=
extractor
.
readSetupHeaders
(
extractorInput
,
new
ParsableByteArray
(
new
byte
[
255
*
255
],
0
));
assertNotNull
(
vorbisSetup
.
idHeader
);
assertNotNull
(
vorbisSetup
.
commentHeader
);
assertNotNull
(
vorbisSetup
.
setupHeaderData
);
assertNotNull
(
vorbisSetup
.
modes
);
assertEquals
(
45
,
vorbisSetup
.
commentHeader
.
length
);
assertEquals
(
30
,
vorbisSetup
.
idHeader
.
data
.
length
);
assertEquals
(
3597
,
vorbisSetup
.
setupHeaderData
.
length
);
assertEquals
(-
1
,
vorbisSetup
.
idHeader
.
bitrateMax
);
assertEquals
(-
1
,
vorbisSetup
.
idHeader
.
bitrateMin
);
assertEquals
(
66666
,
vorbisSetup
.
idHeader
.
bitrateNominal
);
assertEquals
(
512
,
vorbisSetup
.
idHeader
.
blockSize0
);
assertEquals
(
1024
,
vorbisSetup
.
idHeader
.
blockSize1
);
assertEquals
(
2
,
vorbisSetup
.
idHeader
.
channels
);
assertTrue
(
vorbisSetup
.
idHeader
.
framingFlag
);
assertEquals
(
22050
,
vorbisSetup
.
idHeader
.
sampleRate
);
assertEquals
(
0
,
vorbisSetup
.
idHeader
.
version
);
assertEquals
(
"Xiph.Org libVorbis I 20030909"
,
vorbisSetup
.
commentHeader
.
vendor
);
assertEquals
(
1
,
vorbisSetup
.
iLogModes
);
assertEquals
(
data
[
data
.
length
-
1
],
vorbisSetup
.
setupHeaderData
[
vorbisSetup
.
setupHeaderData
.
length
-
1
]);
assertFalse
(
vorbisSetup
.
modes
[
0
].
blockFlag
);
assertTrue
(
vorbisSetup
.
modes
[
1
].
blockFlag
);
break
;
}
catch
(
Throwable
e
)
{
Log
.
e
(
TAG
,
e
.
getMessage
(),
e
);
extractorInput
.
resetPeekPosition
();
exceptionCount
++;
}
}
if
(
exceptionCount
>=
maxExceptions
)
{
fail
(
"more than "
+
maxExceptions
+
" exceptions thrown"
);
}
}
}
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/RecordableExtractorInput.java
0 → 100644
View file @
89ce1cce
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer
.
extractor
.
ogg
;
import
com.google.android.exoplayer.C
;
import
com.google.android.exoplayer.extractor.ExtractorInput
;
import
java.io.EOFException
;
import
java.io.IOException
;
/**
* Implementation of {@link ExtractorInput} for testing purpose.
*/
/* package */
class
RecordableExtractorInput
implements
ExtractorInput
{
protected
static
final
byte
STREAM_REVISION
=
0x00
;
private
byte
[]
data
;
private
int
readOffset
;
private
int
writeOffset
;
private
int
peekOffset
;
private
boolean
throwExceptionsAtRead
=
false
;
private
boolean
throwExceptionsAtPeek
=
false
;
private
int
numberOfReadsUntilException
=
1
;
private
int
numberOfPeeksUntilException
=
1
;
private
int
readCounter
;
private
int
peekCounter
;
private
int
maxReadExceptions
=
Integer
.
MAX_VALUE
;
private
int
maxPeekExceptions
=
Integer
.
MAX_VALUE
;
private
int
readExceptionCounter
;
private
int
peekExceptionCounter
;
/**
* Constructs an instance with a initial array of bytes.
*
* @param data the initial data.
* @param writeOffset the {@code writeOffset} from where to start recording.
*/
public
RecordableExtractorInput
(
byte
[]
data
,
int
writeOffset
)
{
this
.
data
=
data
;
this
.
writeOffset
=
writeOffset
;
}
/**
* Constructs an instance with an empty data array with length {@code maxBytes}.
*
* @param maxBytes the maximal number of bytes this {@code ExtractorInput} can store.
*/
public
RecordableExtractorInput
(
int
maxBytes
)
{
this
(
new
byte
[
maxBytes
],
0
);
}
@Override
public
int
read
(
byte
[]
target
,
int
offset
,
int
length
)
throws
IOException
,
InterruptedException
{
readFully
(
target
,
offset
,
length
);
return
isEOF
()
?
C
.
RESULT_END_OF_INPUT
:
length
;
}
@Override
public
boolean
readFully
(
byte
[]
target
,
int
offset
,
int
length
,
boolean
allowEndOfInput
)
throws
IOException
,
InterruptedException
{
readCounter
++;
if
(
throwExceptionsAtRead
&&
readExceptionCounter
<
maxReadExceptions
&&
readCounter
%
numberOfReadsUntilException
==
0
)
{
readCounter
=
0
;
numberOfReadsUntilException
++;
readExceptionCounter
++;
throw
new
IOException
(
"deliberately thrown an exception for testing"
);
}
if
(
readOffset
+
length
>
writeOffset
)
{
if
(!
allowEndOfInput
)
{
throw
new
EOFException
();
}
return
false
;
}
System
.
arraycopy
(
data
,
readOffset
,
target
,
offset
,
length
);
readOffset
+=
length
;
peekOffset
=
readOffset
;
return
true
;
}
@Override
public
void
readFully
(
byte
[]
target
,
int
offset
,
int
length
)
throws
IOException
,
InterruptedException
{
readFully
(
target
,
offset
,
length
,
false
);
}
@Override
public
int
skip
(
int
length
)
throws
IOException
,
InterruptedException
{
skipFully
(
length
);
return
isEOF
()
?
C
.
RESULT_END_OF_INPUT
:
length
;
}
private
boolean
isEOF
()
{
return
readOffset
==
writeOffset
;
}
@Override
public
boolean
skipFully
(
int
length
,
boolean
allowEndOfInput
)
throws
IOException
,
InterruptedException
{
if
(
readOffset
+
length
>=
writeOffset
)
{
if
(!
allowEndOfInput
)
{
throw
new
EOFException
();
}
return
false
;
}
readOffset
+=
length
;
peekOffset
=
readOffset
;
return
true
;
}
@Override
public
void
skipFully
(
int
length
)
throws
IOException
,
InterruptedException
{
skipFully
(
length
,
false
);
}
@Override
public
boolean
peekFully
(
byte
[]
target
,
int
offset
,
int
length
,
boolean
allowEndOfInput
)
throws
IOException
,
InterruptedException
{
peekCounter
++;
if
(
throwExceptionsAtPeek
&&
peekExceptionCounter
<
maxPeekExceptions
&&
peekCounter
%
numberOfPeeksUntilException
==
0
)
{
peekCounter
=
0
;
numberOfPeeksUntilException
++;
peekExceptionCounter
++;
throw
new
IOException
(
"deliberately thrown an exception for testing"
);
}
if
(
peekOffset
+
length
>
writeOffset
)
{
if
(!
allowEndOfInput
)
{
throw
new
EOFException
();
}
return
false
;
}
System
.
arraycopy
(
data
,
peekOffset
,
target
,
offset
,
length
);
peekOffset
+=
length
;
return
true
;
}
@Override
public
void
peekFully
(
byte
[]
target
,
int
offset
,
int
length
)
throws
IOException
,
InterruptedException
{
peekFully
(
target
,
offset
,
length
,
false
);
}
@Override
public
boolean
advancePeekPosition
(
int
length
,
boolean
allowEndOfInput
)
throws
IOException
,
InterruptedException
{
if
(
peekOffset
+
length
>=
writeOffset
)
{
if
(!
allowEndOfInput
)
{
throw
new
EOFException
();
}
return
false
;
}
peekOffset
+=
length
;
return
true
;
}
@Override
public
void
advancePeekPosition
(
int
length
)
throws
IOException
,
InterruptedException
{
advancePeekPosition
(
length
,
false
);
}
@Override
public
void
resetPeekPosition
()
{
peekOffset
=
readOffset
;
}
@Override
public
long
getPosition
()
{
return
readOffset
;
}
@Override
public
long
getLength
()
{
return
writeOffset
;
}
/**
* Records the {@code bytes}.
*
* @param bytes the bytes to record.
*/
public
void
record
(
final
byte
[]
bytes
)
{
System
.
arraycopy
(
bytes
,
0
,
data
,
writeOffset
,
bytes
.
length
);
writeOffset
+=
bytes
.
length
;
}
/** Records a single byte. **/
public
void
record
(
byte
b
)
{
record
(
new
byte
[]{
b
});
}
/**
* Gets a byte array with length {@code length} with ascending values starting from 0 (zero).
*
* @param length the length of the array.
* @return an array of bytes with ascending values.
*/
public
static
byte
[]
getBytesGrowingValues
(
int
length
)
{
return
fillBytesGrowingValues
(
new
byte
[
length
],
length
,
(
byte
)
0
);
}
/**
* Gets a byte array with length {@code length} with ascending values starting
* from {@code startValue}.
*
* @param length the length of the array.
* @param startValue the value from which to start.
* @return an array of bytes with ascending values starting from {@code startValue}.
*/
public
static
byte
[]
getBytesGrowingValues
(
int
length
,
byte
startValue
)
{
return
fillBytesGrowingValues
(
new
byte
[
length
],
length
,
startValue
);
}
/**
* Fills the byte array passed as argument with ascending values.
*
* @param bytes the byte array to fill with values.
* @param limit the number of bytes to set in the array.
* @param startValue the startValue from which the values in the array have to start.
*/
public
static
byte
[]
fillBytesGrowingValues
(
byte
[]
bytes
,
int
limit
,
byte
startValue
)
{
for
(
int
i
=
0
;
i
<
bytes
.
length
;
i
++)
{
if
(
i
<
limit
)
{
bytes
[
i
]
=
(
byte
)
((
i
+
startValue
)
%
255
);
}
else
{
bytes
[
i
]
=
0
;
}
}
return
bytes
;
}
public
void
setMaxReadExceptions
(
int
maxReadExceptions
)
{
this
.
maxReadExceptions
=
maxReadExceptions
;
}
public
void
setMaxPeekExceptions
(
int
maxPeekExceptions
)
{
this
.
maxPeekExceptions
=
maxPeekExceptions
;
}
public
void
setNumberOfReadsUntilException
(
int
numberOfReadsUntilException
)
{
this
.
numberOfReadsUntilException
=
numberOfReadsUntilException
;
}
public
void
setNumberOfPeeksUntilException
(
int
numberOfPeeksUntilException
)
{
this
.
numberOfPeeksUntilException
=
numberOfPeeksUntilException
;
}
public
void
doThrowExceptionsAtRead
(
boolean
throwExceptionsAtRead
)
{
this
.
throwExceptionsAtRead
=
throwExceptionsAtRead
;
}
public
void
doThrowExceptionsAtPeek
(
boolean
throwExceptionsAtPeek
)
{
this
.
throwExceptionsAtPeek
=
throwExceptionsAtPeek
;
}
}
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/RecordableOggExtractorInput.java
0 → 100644
View file @
89ce1cce
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer
.
extractor
.
ogg
;
/**
* A {@link RecordableOggExtractorInput} with convenient methods to record an OGG byte stream.
*/
/* package */
final
class
RecordableOggExtractorInput
extends
RecordableExtractorInput
{
private
long
pageSequenceCounter
;
public
RecordableOggExtractorInput
(
byte
[]
data
,
int
writeOffset
)
{
super
(
data
,
writeOffset
);
pageSequenceCounter
=
1000
;
}
public
RecordableOggExtractorInput
(
int
maxBytes
)
{
this
(
new
byte
[
maxBytes
],
0
);
}
/**
* Syntax sugar to make tests more readable.
*
* @param laces the laces to record to the data.
*/
protected
void
recordOggLaces
(
final
byte
[]
laces
)
{
record
(
laces
);
}
/**
* Syntax sugar to make tests more readable.
*
* @param packet the packet bytes to record to the data.
*/
protected
void
recordOggPacket
(
final
byte
[]
packet
)
{
record
(
packet
);
}
protected
void
recordOggHeader
(
final
byte
headerType
,
final
long
granule
,
final
byte
pageSegmentCount
)
{
record
((
byte
)
0x4F
);
// O
record
((
byte
)
0x67
);
// g
record
((
byte
)
0x67
);
// g
record
((
byte
)
0x53
);
// S
record
(
STREAM_REVISION
);
record
(
headerType
);
recordGranulePosition
(
granule
);
record
((
byte
)
0x00
);
// LSB of data serial number
record
((
byte
)
0x10
);
record
((
byte
)
0x00
);
record
((
byte
)
0x00
);
// MSB of data serial number
recordPageSequenceCounter
();
record
((
byte
)
0x00
);
// LSB of page checksum
record
((
byte
)
0x00
);
record
((
byte
)
0x00
);
record
((
byte
)
0x00
);
// MSB of page checksum
record
(
pageSegmentCount
);
// 0 - 255
}
protected
void
recordGranulePosition
(
long
granule
)
{
record
((
byte
)
(
granule
&
0xFF
));
record
((
byte
)
((
granule
>>
8
)
&
0xFF
));
record
((
byte
)
((
granule
>>
16
)
&
0xFF
));
record
((
byte
)
((
granule
>>
24
)
&
0xFF
));
record
((
byte
)
((
granule
>>
32
)
&
0xFF
));
record
((
byte
)
((
granule
>>
40
)
&
0xFF
));
record
((
byte
)
((
granule
>>
48
)
&
0xFF
));
record
((
byte
)
((
granule
>>
56
)
&
0xFF
));
}
protected
void
recordPageSequenceCounter
()
{
record
((
byte
)
(
pageSequenceCounter
&
0xFF
));
record
((
byte
)
((
pageSequenceCounter
>>
8
)
&
0xFF
));
record
((
byte
)
((
pageSequenceCounter
>>
16
)
&
0xFF
));
record
((
byte
)
((
pageSequenceCounter
++
>>
24
)
&
0xFF
));
}
}
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/TestData.java
0 → 100644
View file @
89ce1cce
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer
.
extractor
.
ogg
;
/**
* Provides ogg/vorbis test data in bytes for unit tests.
*/
/* package */
final
class
TestData
{
/**
* Returns the initial two pages of bytes which by spec contain the three vorbis header packets:
* identification, comment and setup header.
*/
public
static
byte
[]
getVorbisHeaderPages
()
{
byte
[]
data
=
new
byte
[
VORBIS_HEADER_PAGES
.
length
];
System
.
arraycopy
(
VORBIS_HEADER_PAGES
,
0
,
data
,
0
,
VORBIS_HEADER_PAGES
.
length
);
return
data
;
}
/**
* Returns a valid vorbis identification header in bytes.
*/
public
static
byte
[]
getIdentificationHeaderData
()
{
int
idHeaderStart
=
28
;
int
idHeaderLength
=
30
;
byte
[]
idHeaderData
=
new
byte
[
idHeaderLength
];
System
.
arraycopy
(
VORBIS_HEADER_PAGES
,
idHeaderStart
,
idHeaderData
,
0
,
idHeaderLength
);
return
idHeaderData
;
}
/**
* Returns a valid vorbis comment header with 3 comments including utf8 chars in bytes.
*/
public
static
byte
[]
getCommentHeaderDataUTF8
()
{
byte
[]
commentHeaderData
=
new
byte
[
COMMENT_HEADER_WITH_UTF8
.
length
];
System
.
arraycopy
(
COMMENT_HEADER_WITH_UTF8
,
0
,
commentHeaderData
,
0
,
COMMENT_HEADER_WITH_UTF8
.
length
);
return
commentHeaderData
;
}
/**
* Returns a valid vorbis setup header in bytes.
*/
public
static
byte
[]
getSetupHeaderData
()
{
int
setupHeaderStart
=
146
;
int
setupHeaderLength
=
VORBIS_HEADER_PAGES
.
length
-
setupHeaderStart
;
byte
[]
setupHeaderData
=
new
byte
[
setupHeaderLength
];
System
.
arraycopy
(
VORBIS_HEADER_PAGES
,
setupHeaderStart
,
setupHeaderData
,
0
,
setupHeaderLength
);
return
setupHeaderData
;
}
private
static
final
byte
[]
COMMENT_HEADER_WITH_UTF8
=
{
(
byte
)
0x03
,
(
byte
)
0x76
,
(
byte
)
0x6f
,
(
byte
)
0x72
,
// 3, v, o, r,
(
byte
)
0x62
,
(
byte
)
0x69
,
(
byte
)
0x73
,
(
byte
)
0x2b
,
// b, i, s, .
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x58
,
(
byte
)
0x69
,
(
byte
)
0x70
,
(
byte
)
0x68
,
(
byte
)
0x2e
,
(
byte
)
0x4f
,
(
byte
)
0x72
,
(
byte
)
0x67
,
(
byte
)
0x20
,
(
byte
)
0x6c
,
(
byte
)
0x69
,
(
byte
)
0x62
,
(
byte
)
0x56
,
(
byte
)
0x6f
,
(
byte
)
0x72
,
(
byte
)
0x62
,
(
byte
)
0x69
,
(
byte
)
0x73
,
(
byte
)
0x20
,
(
byte
)
0x49
,
(
byte
)
0x20
,
(
byte
)
0x32
,
(
byte
)
0x30
,
(
byte
)
0x31
,
(
byte
)
0x32
,
(
byte
)
0x30
,
(
byte
)
0x32
,
(
byte
)
0x30
,
(
byte
)
0x33
,
(
byte
)
0x20
,
(
byte
)
0x28
,
(
byte
)
0x4f
,
(
byte
)
0x6d
,
(
byte
)
0x6e
,
(
byte
)
0x69
,
(
byte
)
0x70
,
(
byte
)
0x72
,
(
byte
)
0x65
,
(
byte
)
0x73
,
(
byte
)
0x65
,
(
byte
)
0x6e
,
(
byte
)
0x74
,
(
byte
)
0x29
,
(
byte
)
0x03
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x0a
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x41
,
(
byte
)
0x4c
,
(
byte
)
0x42
,
(
byte
)
0x55
,
(
byte
)
0x4d
,
(
byte
)
0x3d
,
(
byte
)
0xc3
,
(
byte
)
0xa4
,
(
byte
)
0xc3
,
(
byte
)
0xb6
,
(
byte
)
0x13
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x54
,
(
byte
)
0x49
,
(
byte
)
0x54
,
(
byte
)
0x4c
,
(
byte
)
0x45
,
(
byte
)
0x3d
,
(
byte
)
0x41
,
(
byte
)
0x20
,
(
byte
)
0x73
,
(
byte
)
0x61
,
(
byte
)
0x6d
,
(
byte
)
0x70
,
(
byte
)
0x6c
,
(
byte
)
0x65
,
(
byte
)
0x20
,
(
byte
)
0x73
,
(
byte
)
0x6f
,
(
byte
)
0x6e
,
(
byte
)
0x67
,
(
byte
)
0x0d
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x41
,
(
byte
)
0x52
,
(
byte
)
0x54
,
(
byte
)
0x49
,
(
byte
)
0x53
,
(
byte
)
0x54
,
(
byte
)
0x3d
,
(
byte
)
0x47
,
(
byte
)
0x6f
,
(
byte
)
0x6f
,
(
byte
)
0x67
,
(
byte
)
0x6c
,
(
byte
)
0x65
,
(
byte
)
0x01
};
// two OGG pages with 3 packets (id, comment and setup header)
// length: 3743 bytes
private
static
final
byte
[]
VORBIS_HEADER_PAGES
=
{
/* capture pattern ogg header 1 */
(
byte
)
0x4f
,
(
byte
)
0x67
,
(
byte
)
0x67
,
(
byte
)
0x53
,
// O,g,g,S : start pos 0
(
byte
)
0x00
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x5e
,
(
byte
)
0x5f
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x83
,
(
byte
)
0x36
,
(
byte
)
0xe3
,
(
byte
)
0x49
,
(
byte
)
0x01
,
(
byte
)
0x1e
,
/* capture pattern vorbis id header */
(
byte
)
0x01
,
(
byte
)
0x76
,
(
byte
)
0x6f
,
(
byte
)
0x72
,
// 1,v,o,r : start pos 28
(
byte
)
0x62
,
(
byte
)
0x69
,
(
byte
)
0x73
,
(
byte
)
0x00
,
// b,i,s,.
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x02
,
(
byte
)
0x22
,
(
byte
)
0x56
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0x6a
,
(
byte
)
0x04
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
/* capture pattern ogg header 2 */
(
byte
)
0xa9
,
(
byte
)
0x01
,
(
byte
)
0x4f
,
(
byte
)
0x67
,
// .,.,O,g : start pos 86
(
byte
)
0x67
,
(
byte
)
0x53
,
(
byte
)
0x00
,
(
byte
)
0x00
,
// g,S,.,.
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x5e
,
(
byte
)
0x5f
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x69
,
(
byte
)
0xf8
,
(
byte
)
0xeb
,
(
byte
)
0xe1
,
(
byte
)
0x10
,
(
byte
)
0x2d
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
(
byte
)
0xff
,
/* capture pattern vorbis comment header*/
(
byte
)
0x1b
,
(
byte
)
0x03
,
(
byte
)
0x76
,
(
byte
)
0x6f
,
// .,3,v,o : start pos 101
(
byte
)
0x72
,
(
byte
)
0x62
,
(
byte
)
0x69
,
(
byte
)
0x73
,
// r,b,i,s
(
byte
)
0x1d
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x58
,
(
byte
)
0x69
,
(
byte
)
0x70
,
(
byte
)
0x68
,
(
byte
)
0x2e
,
(
byte
)
0x4f
,
(
byte
)
0x72
,
(
byte
)
0x67
,
(
byte
)
0x20
,
(
byte
)
0x6c
,
(
byte
)
0x69
,
(
byte
)
0x62
,
(
byte
)
0x56
,
(
byte
)
0x6f
,
(
byte
)
0x72
,
(
byte
)
0x62
,
(
byte
)
0x69
,
(
byte
)
0x73
,
(
byte
)
0x20
,
(
byte
)
0x49
,
(
byte
)
0x20
,
(
byte
)
0x32
,
(
byte
)
0x30
,
(
byte
)
0x30
,
(
byte
)
0x33
,
(
byte
)
0x30
,
(
byte
)
0x39
,
(
byte
)
0x30
,
(
byte
)
0x39
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
/* capture pattern vorbis setup header */
(
byte
)
0x00
,
(
byte
)
0x01
,
(
byte
)
0x05
,
(
byte
)
0x76
,
// .,.,5,v : start pos 146
(
byte
)
0x6f
,
(
byte
)
0x72
,
(
byte
)
0x62
,
(
byte
)
0x69
,
// o,r,b,i
(
byte
)
0x73
,
(
byte
)
0x22
,
(
byte
)
0x42
,
(
byte
)
0x43
,
// s,.
(
byte
)
0x56
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x40
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x18
,
(
byte
)
0x42
,
(
byte
)
0x10
,
(
byte
)
0x2a
,
(
byte
)
0x05
,
(
byte
)
0xad
,
(
byte
)
0x63
,
(
byte
)
0x8e
,
(
byte
)
0x3a
,
(
byte
)
0xc8
,
(
byte
)
0x15
,
(
byte
)
0x21
,
(
byte
)
0x8c
,
(
byte
)
0x19
,
(
byte
)
0xa2
,
(
byte
)
0xa0
,
(
byte
)
0x42
,
(
byte
)
0xca
,
(
byte
)
0x29
,
(
byte
)
0xc7
,
(
byte
)
0x1d
,
(
byte
)
0x42
,
(
byte
)
0xd0
,
(
byte
)
0x21
,
(
byte
)
0xa3
,
(
byte
)
0x24
,
(
byte
)
0x43
,
(
byte
)
0x88
,
(
byte
)
0x3a
,
(
byte
)
0xc6
,
(
byte
)
0x35
,
(
byte
)
0xc7
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x47
,
(
byte
)
0xb9
,
(
byte
)
0x64
,
(
byte
)
0x8a
,
(
byte
)
0x42
,
(
byte
)
0xc9
,
(
byte
)
0x81
,
(
byte
)
0xd0
,
(
byte
)
0x90
,
(
byte
)
0x55
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x40
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0xa4
,
(
byte
)
0x1c
,
(
byte
)
0x57
,
(
byte
)
0x50
,
(
byte
)
0x72
,
(
byte
)
0x49
,
(
byte
)
0x2d
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xa3
,
(
byte
)
0x18
,
(
byte
)
0x57
,
(
byte
)
0xcc
,
(
byte
)
0x71
,
(
byte
)
0xe8
,
(
byte
)
0x20
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xe5
,
(
byte
)
0x20
,
(
byte
)
0x67
,
(
byte
)
0xcc
,
(
byte
)
0x71
,
(
byte
)
0x09
,
(
byte
)
0x25
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0x8e
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x92
,
(
byte
)
0x72
,
(
byte
)
0x8e
,
(
byte
)
0x31
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xa3
,
(
byte
)
0x18
,
(
byte
)
0x57
,
(
byte
)
0x0e
,
(
byte
)
0x72
,
(
byte
)
0x29
,
(
byte
)
0x2d
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0x81
,
(
byte
)
0x14
,
(
byte
)
0x47
,
(
byte
)
0x8a
,
(
byte
)
0x71
,
(
byte
)
0xa7
,
(
byte
)
0x18
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xa4
,
(
byte
)
0x1c
,
(
byte
)
0x47
,
(
byte
)
0x8a
,
(
byte
)
0x71
,
(
byte
)
0xa8
,
(
byte
)
0x18
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0x6d
,
(
byte
)
0x31
,
(
byte
)
0xb7
,
(
byte
)
0x92
,
(
byte
)
0x72
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xe6
,
(
byte
)
0x20
,
(
byte
)
0x87
,
(
byte
)
0x52
,
(
byte
)
0x72
,
(
byte
)
0xae
,
(
byte
)
0x35
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xa4
,
(
byte
)
0x18
,
(
byte
)
0x67
,
(
byte
)
0x0e
,
(
byte
)
0x72
,
(
byte
)
0x0b
,
(
byte
)
0x25
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xc6
,
(
byte
)
0x20
,
(
byte
)
0x67
,
(
byte
)
0xcc
,
(
byte
)
0x71
,
(
byte
)
0xeb
,
(
byte
)
0x20
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0x8c
,
(
byte
)
0x35
,
(
byte
)
0xb7
,
(
byte
)
0xd4
,
(
byte
)
0x72
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0x6e
,
(
byte
)
0x31
,
(
byte
)
0xe7
,
(
byte
)
0x16
,
(
byte
)
0x73
,
(
byte
)
0xae
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x1c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0x20
,
(
byte
)
0x34
,
(
byte
)
0x64
,
(
byte
)
0x15
,
(
byte
)
0x00
,
(
byte
)
0x90
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0xa0
,
(
byte
)
0xa1
,
(
byte
)
0x28
,
(
byte
)
0x8a
,
(
byte
)
0xe2
,
(
byte
)
0x28
,
(
byte
)
0x0e
,
(
byte
)
0x10
,
(
byte
)
0x1a
,
(
byte
)
0xb2
,
(
byte
)
0x0a
,
(
byte
)
0x00
,
(
byte
)
0xc8
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x40
,
(
byte
)
0x71
,
(
byte
)
0x14
,
(
byte
)
0x47
,
(
byte
)
0x91
,
(
byte
)
0x14
,
(
byte
)
0x4b
,
(
byte
)
0xb1
,
(
byte
)
0x1c
,
(
byte
)
0xcb
,
(
byte
)
0xd1
,
(
byte
)
0x24
,
(
byte
)
0x0d
,
(
byte
)
0x08
,
(
byte
)
0x0d
,
(
byte
)
0x59
,
(
byte
)
0x05
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x08
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0xa0
,
(
byte
)
0x48
,
(
byte
)
0x86
,
(
byte
)
0xa4
,
(
byte
)
0x48
,
(
byte
)
0x8a
,
(
byte
)
0xa5
,
(
byte
)
0x58
,
(
byte
)
0x8e
,
(
byte
)
0x66
,
(
byte
)
0x69
,
(
byte
)
0x9e
,
(
byte
)
0x26
,
(
byte
)
0x7a
,
(
byte
)
0xa2
,
(
byte
)
0x28
,
(
byte
)
0x9a
,
(
byte
)
0xa2
,
(
byte
)
0x2a
,
(
byte
)
0xab
,
(
byte
)
0xb2
,
(
byte
)
0x69
,
(
byte
)
0xca
,
(
byte
)
0xb2
,
(
byte
)
0x2c
,
(
byte
)
0xcb
,
(
byte
)
0xb2
,
(
byte
)
0xeb
,
(
byte
)
0xba
,
(
byte
)
0x2e
,
(
byte
)
0x10
,
(
byte
)
0x1a
,
(
byte
)
0xb2
,
(
byte
)
0x0a
,
(
byte
)
0x00
,
(
byte
)
0x48
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x50
,
(
byte
)
0x51
,
(
byte
)
0x14
,
(
byte
)
0xc5
,
(
byte
)
0x70
,
(
byte
)
0x14
,
(
byte
)
0x07
,
(
byte
)
0x08
,
(
byte
)
0x0d
,
(
byte
)
0x59
,
(
byte
)
0x05
,
(
byte
)
0x00
,
(
byte
)
0x64
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x08
,
(
byte
)
0x60
,
(
byte
)
0x28
,
(
byte
)
0x8a
,
(
byte
)
0xa3
,
(
byte
)
0x38
,
(
byte
)
0x8e
,
(
byte
)
0xe4
,
(
byte
)
0x58
,
(
byte
)
0x92
,
(
byte
)
0xa5
,
(
byte
)
0x59
,
(
byte
)
0x9e
,
(
byte
)
0x07
,
(
byte
)
0x84
,
(
byte
)
0x86
,
(
byte
)
0xac
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x80
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x04
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x50
,
(
byte
)
0x0c
,
(
byte
)
0x47
,
(
byte
)
0xb1
,
(
byte
)
0x14
,
(
byte
)
0x4d
,
(
byte
)
0xf1
,
(
byte
)
0x24
,
(
byte
)
0xcf
,
(
byte
)
0xf2
,
(
byte
)
0x3c
,
(
byte
)
0xcf
,
(
byte
)
0xf3
,
(
byte
)
0x3c
,
(
byte
)
0xcf
,
(
byte
)
0xf3
,
(
byte
)
0x3c
,
(
byte
)
0xcf
,
(
byte
)
0xf3
,
(
byte
)
0x3c
,
(
byte
)
0xcf
,
(
byte
)
0xf3
,
(
byte
)
0x3c
,
(
byte
)
0xcf
,
(
byte
)
0xf3
,
(
byte
)
0x3c
,
(
byte
)
0xcf
,
(
byte
)
0xf3
,
(
byte
)
0x3c
,
(
byte
)
0x0d
,
(
byte
)
0x08
,
(
byte
)
0x0d
,
(
byte
)
0x59
,
(
byte
)
0x05
,
(
byte
)
0x00
,
(
byte
)
0x20
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x82
,
(
byte
)
0x28
,
(
byte
)
0x64
,
(
byte
)
0x18
,
(
byte
)
0x03
,
(
byte
)
0x42
,
(
byte
)
0x43
,
(
byte
)
0x56
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x40
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x1a
,
(
byte
)
0x19
,
(
byte
)
0x43
,
(
byte
)
0x9d
,
(
byte
)
0x52
,
(
byte
)
0x12
,
(
byte
)
0x5c
,
(
byte
)
0x0a
,
(
byte
)
0x16
,
(
byte
)
0x42
,
(
byte
)
0x1c
,
(
byte
)
0x11
,
(
byte
)
0x43
,
(
byte
)
0x1d
,
(
byte
)
0x42
,
(
byte
)
0xce
,
(
byte
)
0x43
,
(
byte
)
0xa9
,
(
byte
)
0xa5
,
(
byte
)
0x83
,
(
byte
)
0xe0
,
(
byte
)
0x29
,
(
byte
)
0x85
,
(
byte
)
0x25
,
(
byte
)
0x63
,
(
byte
)
0xd2
,
(
byte
)
0x53
,
(
byte
)
0xac
,
(
byte
)
0x41
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x7c
,
(
byte
)
0xef
,
(
byte
)
0x3d
,
(
byte
)
0xf7
,
(
byte
)
0xde
,
(
byte
)
0x7b
,
(
byte
)
0xef
,
(
byte
)
0x81
,
(
byte
)
0xd0
,
(
byte
)
0x90
,
(
byte
)
0x55
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x61
,
(
byte
)
0x14
,
(
byte
)
0x38
,
(
byte
)
0x88
,
(
byte
)
0x81
,
(
byte
)
0xc7
,
(
byte
)
0x24
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0x62
,
(
byte
)
0x14
,
(
byte
)
0x27
,
(
byte
)
0x44
,
(
byte
)
0x71
,
(
byte
)
0xa6
,
(
byte
)
0x20
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0xe5
,
(
byte
)
0x24
,
(
byte
)
0x58
,
(
byte
)
0xca
,
(
byte
)
0x79
,
(
byte
)
0xe8
,
(
byte
)
0x24
,
(
byte
)
0x08
,
(
byte
)
0xdd
,
(
byte
)
0x83
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0xb8
,
(
byte
)
0x9c
,
(
byte
)
0x7b
,
(
byte
)
0xcb
,
(
byte
)
0xb9
,
(
byte
)
0xf7
,
(
byte
)
0xde
,
(
byte
)
0x7b
,
(
byte
)
0x20
,
(
byte
)
0x34
,
(
byte
)
0x64
,
(
byte
)
0x15
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x08
,
(
byte
)
0x00
,
(
byte
)
0xc0
,
(
byte
)
0x20
,
(
byte
)
0x84
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x08
,
(
byte
)
0x29
,
(
byte
)
0xa4
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x48
,
(
byte
)
0x29
,
(
byte
)
0xa6
,
(
byte
)
0x98
,
(
byte
)
0x62
,
(
byte
)
0x8a
,
(
byte
)
0x29
,
(
byte
)
0xc7
,
(
byte
)
0x1c
,
(
byte
)
0x73
,
(
byte
)
0xcc
,
(
byte
)
0x31
,
(
byte
)
0xc7
,
(
byte
)
0x20
,
(
byte
)
0x83
,
(
byte
)
0x0c
,
(
byte
)
0x32
,
(
byte
)
0xe8
,
(
byte
)
0xa0
,
(
byte
)
0x93
,
(
byte
)
0x4e
,
(
byte
)
0x3a
,
(
byte
)
0xc9
,
(
byte
)
0xa4
,
(
byte
)
0x92
,
(
byte
)
0x4e
,
(
byte
)
0x3a
,
(
byte
)
0xca
,
(
byte
)
0x24
,
(
byte
)
0xa3
,
(
byte
)
0x8e
,
(
byte
)
0x52
,
(
byte
)
0x6b
,
(
byte
)
0x29
,
(
byte
)
0xb5
,
(
byte
)
0x14
,
(
byte
)
0x53
,
(
byte
)
0x4c
,
(
byte
)
0xb1
,
(
byte
)
0xe5
,
(
byte
)
0x16
,
(
byte
)
0x63
,
(
byte
)
0xad
,
(
byte
)
0xb5
,
(
byte
)
0xd6
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xaf
,
(
byte
)
0x41
,
(
byte
)
0x29
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x23
,
(
byte
)
0x08
,
(
byte
)
0x0d
,
(
byte
)
0x59
,
(
byte
)
0x05
,
(
byte
)
0x00
,
(
byte
)
0x80
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x06
,
(
byte
)
0x19
,
(
byte
)
0x64
,
(
byte
)
0x90
,
(
byte
)
0x41
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0x14
,
(
byte
)
0x52
,
(
byte
)
0x48
,
(
byte
)
0x29
,
(
byte
)
0xa6
,
(
byte
)
0x98
,
(
byte
)
0x72
,
(
byte
)
0xcc
,
(
byte
)
0x31
,
(
byte
)
0xc7
,
(
byte
)
0x1c
,
(
byte
)
0x03
,
(
byte
)
0x42
,
(
byte
)
0x43
,
(
byte
)
0x56
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x80
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x1c
,
(
byte
)
0x45
,
(
byte
)
0x52
,
(
byte
)
0x24
,
(
byte
)
0x47
,
(
byte
)
0x72
,
(
byte
)
0x24
,
(
byte
)
0x47
,
(
byte
)
0x92
,
(
byte
)
0x24
,
(
byte
)
0xc9
,
(
byte
)
0x92
,
(
byte
)
0x2c
,
(
byte
)
0x49
,
(
byte
)
0x93
,
(
byte
)
0x3c
,
(
byte
)
0xcb
,
(
byte
)
0xb3
,
(
byte
)
0x3c
,
(
byte
)
0xcb
,
(
byte
)
0xb3
,
(
byte
)
0x3c
,
(
byte
)
0x4d
,
(
byte
)
0xd4
,
(
byte
)
0x44
,
(
byte
)
0x4d
,
(
byte
)
0x15
,
(
byte
)
0x55
,
(
byte
)
0xd5
,
(
byte
)
0x55
,
(
byte
)
0x6d
,
(
byte
)
0xd7
,
(
byte
)
0xf6
,
(
byte
)
0x6d
,
(
byte
)
0x5f
,
(
byte
)
0xf6
,
(
byte
)
0x6d
,
(
byte
)
0xdf
,
(
byte
)
0xd5
,
(
byte
)
0x65
,
(
byte
)
0xdf
,
(
byte
)
0xf6
,
(
byte
)
0x65
,
(
byte
)
0xdb
,
(
byte
)
0xd5
,
(
byte
)
0x65
,
(
byte
)
0x5d
,
(
byte
)
0x96
,
(
byte
)
0x65
,
(
byte
)
0xdd
,
(
byte
)
0xb5
,
(
byte
)
0x6d
,
(
byte
)
0x5d
,
(
byte
)
0xd6
,
(
byte
)
0x5d
,
(
byte
)
0x5d
,
(
byte
)
0xd7
,
(
byte
)
0x75
,
(
byte
)
0x5d
,
(
byte
)
0xd7
,
(
byte
)
0x75
,
(
byte
)
0x5d
,
(
byte
)
0xd7
,
(
byte
)
0x75
,
(
byte
)
0x5d
,
(
byte
)
0xd7
,
(
byte
)
0x75
,
(
byte
)
0x5d
,
(
byte
)
0xd7
,
(
byte
)
0x75
,
(
byte
)
0x5d
,
(
byte
)
0xd7
,
(
byte
)
0x81
,
(
byte
)
0xd0
,
(
byte
)
0x90
,
(
byte
)
0x55
,
(
byte
)
0x00
,
(
byte
)
0x80
,
(
byte
)
0x04
,
(
byte
)
0x00
,
(
byte
)
0x80
,
(
byte
)
0x8e
,
(
byte
)
0xe4
,
(
byte
)
0x38
,
(
byte
)
0x8e
,
(
byte
)
0xe4
,
(
byte
)
0x38
,
(
byte
)
0x8e
,
(
byte
)
0xe4
,
(
byte
)
0x48
,
(
byte
)
0x8e
,
(
byte
)
0xa4
,
(
byte
)
0x48
,
(
byte
)
0x0a
,
(
byte
)
0x10
,
(
byte
)
0x1a
,
(
byte
)
0xb2
,
(
byte
)
0x0a
,
(
byte
)
0x00
,
(
byte
)
0x90
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x00
,
(
byte
)
0x80
,
(
byte
)
0xa3
,
(
byte
)
0x38
,
(
byte
)
0x8a
,
(
byte
)
0xe3
,
(
byte
)
0x48
,
(
byte
)
0x8e
,
(
byte
)
0xe4
,
(
byte
)
0x58
,
(
byte
)
0x8e
,
(
byte
)
0x25
,
(
byte
)
0x59
,
(
byte
)
0x92
,
(
byte
)
0x26
,
(
byte
)
0x69
,
(
byte
)
0x96
,
(
byte
)
0x67
,
(
byte
)
0x79
,
(
byte
)
0x96
,
(
byte
)
0xa7
,
(
byte
)
0x79
,
(
byte
)
0x9a
,
(
byte
)
0xa8
,
(
byte
)
0x89
,
(
byte
)
0x1e
,
(
byte
)
0x10
,
(
byte
)
0x1a
,
(
byte
)
0xb2
,
(
byte
)
0x0a
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x04
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x80
,
(
byte
)
0xa2
,
(
byte
)
0x28
,
(
byte
)
0x8a
,
(
byte
)
0xa3
,
(
byte
)
0x38
,
(
byte
)
0x8e
,
(
byte
)
0x24
,
(
byte
)
0x59
,
(
byte
)
0x96
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0x9e
,
(
byte
)
0xa7
,
(
byte
)
0x7a
,
(
byte
)
0xa2
,
(
byte
)
0x28
,
(
byte
)
0x9a
,
(
byte
)
0xaa
,
(
byte
)
0xaa
,
(
byte
)
0x8a
,
(
byte
)
0xa6
,
(
byte
)
0xa9
,
(
byte
)
0xaa
,
(
byte
)
0xaa
,
(
byte
)
0x6a
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0x02
,
(
byte
)
0xa1
,
(
byte
)
0x21
,
(
byte
)
0xab
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x09
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x1d
,
(
byte
)
0xc7
,
(
byte
)
0x71
,
(
byte
)
0x1c
,
(
byte
)
0x47
,
(
byte
)
0x71
,
(
byte
)
0x1c
,
(
byte
)
0xc7
,
(
byte
)
0x71
,
(
byte
)
0x24
,
(
byte
)
0x47
,
(
byte
)
0x92
,
(
byte
)
0x24
,
(
byte
)
0x20
,
(
byte
)
0x34
,
(
byte
)
0x64
,
(
byte
)
0x15
,
(
byte
)
0x00
,
(
byte
)
0x20
,
(
byte
)
0x03
,
(
byte
)
0x00
,
(
byte
)
0x20
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x43
,
(
byte
)
0x51
,
(
byte
)
0x1c
,
(
byte
)
0x45
,
(
byte
)
0x72
,
(
byte
)
0x2c
,
(
byte
)
0xc7
,
(
byte
)
0x92
,
(
byte
)
0x34
,
(
byte
)
0x4b
,
(
byte
)
0xb3
,
(
byte
)
0x3c
,
(
byte
)
0xcb
,
(
byte
)
0xd3
,
(
byte
)
0x44
,
(
byte
)
0xcf
,
(
byte
)
0xf4
,
(
byte
)
0x5c
,
(
byte
)
0x51
,
(
byte
)
0x36
,
(
byte
)
0x75
,
(
byte
)
0x53
,
(
byte
)
0x57
,
(
byte
)
0x6d
,
(
byte
)
0x20
,
(
byte
)
0x34
,
(
byte
)
0x64
,
(
byte
)
0x15
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x08
,
(
byte
)
0x00
,
(
byte
)
0x20
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0xc7
,
(
byte
)
0x73
,
(
byte
)
0x3c
,
(
byte
)
0xc7
,
(
byte
)
0x73
,
(
byte
)
0x3c
,
(
byte
)
0xc9
,
(
byte
)
0x93
,
(
byte
)
0x3c
,
(
byte
)
0xcb
,
(
byte
)
0x73
,
(
byte
)
0x3c
,
(
byte
)
0xc7
,
(
byte
)
0x93
,
(
byte
)
0x3c
,
(
byte
)
0x49
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0x03
,
(
byte
)
0x42
,
(
byte
)
0x43
,
(
byte
)
0x56
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x64
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x90
,
(
byte
)
0x02
,
(
byte
)
0xcf
,
(
byte
)
0x42
,
(
byte
)
0x29
,
(
byte
)
0x2d
,
(
byte
)
0x46
,
(
byte
)
0x02
,
(
byte
)
0x1c
,
(
byte
)
0x88
,
(
byte
)
0x98
,
(
byte
)
0xa3
,
(
byte
)
0xd8
,
(
byte
)
0x7b
,
(
byte
)
0xef
,
(
byte
)
0xbd
,
(
byte
)
0xf7
,
(
byte
)
0xde
,
(
byte
)
0x7b
,
(
byte
)
0x65
,
(
byte
)
0x3c
,
(
byte
)
0x92
,
(
byte
)
0x88
,
(
byte
)
0x49
,
(
byte
)
0xed
,
(
byte
)
0x31
,
(
byte
)
0xf4
,
(
byte
)
0xd4
,
(
byte
)
0x31
,
(
byte
)
0x07
,
(
byte
)
0xb1
,
(
byte
)
0x67
,
(
byte
)
0xc6
,
(
byte
)
0x23
,
(
byte
)
0x66
,
(
byte
)
0x94
,
(
byte
)
0xa3
,
(
byte
)
0xd8
,
(
byte
)
0x29
,
(
byte
)
0xcf
,
(
byte
)
0x1c
,
(
byte
)
0x42
,
(
byte
)
0x0c
,
(
byte
)
0x62
,
(
byte
)
0xe8
,
(
byte
)
0x3c
,
(
byte
)
0x74
,
(
byte
)
0x4a
,
(
byte
)
0x31
,
(
byte
)
0x88
,
(
byte
)
0x29
,
(
byte
)
0xf5
,
(
byte
)
0x52
,
(
byte
)
0x32
,
(
byte
)
0xc6
,
(
byte
)
0x20
,
(
byte
)
0xc6
,
(
byte
)
0xd8
,
(
byte
)
0x63
,
(
byte
)
0x0c
,
(
byte
)
0x21
,
(
byte
)
0x94
,
(
byte
)
0x18
,
(
byte
)
0x08
,
(
byte
)
0x0d
,
(
byte
)
0x59
,
(
byte
)
0x21
,
(
byte
)
0x00
,
(
byte
)
0x84
,
(
byte
)
0x66
,
(
byte
)
0x00
,
(
byte
)
0x18
,
(
byte
)
0x24
,
(
byte
)
0x09
,
(
byte
)
0x90
,
(
byte
)
0x34
,
(
byte
)
0x0d
,
(
byte
)
0x90
,
(
byte
)
0x34
,
(
byte
)
0x0d
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x24
,
(
byte
)
0x4f
,
(
byte
)
0x03
,
(
byte
)
0x34
,
(
byte
)
0x51
,
(
byte
)
0x04
,
(
byte
)
0x34
,
(
byte
)
0x4f
,
(
byte
)
0x04
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x49
,
(
byte
)
0xf3
,
(
byte
)
0x00
,
(
byte
)
0x4d
,
(
byte
)
0xf4
,
(
byte
)
0x00
,
(
byte
)
0x4d
,
(
byte
)
0x14
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x90
,
(
byte
)
0x3c
,
(
byte
)
0x0d
,
(
byte
)
0xf0
,
(
byte
)
0x44
,
(
byte
)
0x11
,
(
byte
)
0xd0
,
(
byte
)
0x44
,
(
byte
)
0x11
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x34
,
(
byte
)
0x51
,
(
byte
)
0x04
,
(
byte
)
0x44
,
(
byte
)
0x51
,
(
byte
)
0x05
,
(
byte
)
0x44
,
(
byte
)
0xd5
,
(
byte
)
0x04
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x4d
,
(
byte
)
0x14
,
(
byte
)
0x01
,
(
byte
)
0x4f
,
(
byte
)
0x15
,
(
byte
)
0x01
,
(
byte
)
0xd1
,
(
byte
)
0x54
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x90
,
(
byte
)
0x34
,
(
byte
)
0x0f
,
(
byte
)
0xd0
,
(
byte
)
0x44
,
(
byte
)
0x11
,
(
byte
)
0xf0
,
(
byte
)
0x44
,
(
byte
)
0x11
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x34
,
(
byte
)
0x51
,
(
byte
)
0x04
,
(
byte
)
0x44
,
(
byte
)
0xd5
,
(
byte
)
0x04
,
(
byte
)
0x3c
,
(
byte
)
0x51
,
(
byte
)
0x05
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x4d
,
(
byte
)
0x14
,
(
byte
)
0x01
,
(
byte
)
0xd1
,
(
byte
)
0x54
,
(
byte
)
0x01
,
(
byte
)
0x51
,
(
byte
)
0x15
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x04
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x04
,
(
byte
)
0x38
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x04
,
(
byte
)
0x58
,
(
byte
)
0x08
,
(
byte
)
0x85
,
(
byte
)
0x86
,
(
byte
)
0xac
,
(
byte
)
0x08
,
(
byte
)
0x00
,
(
byte
)
0xe2
,
(
byte
)
0x04
,
(
byte
)
0x00
,
(
byte
)
0x04
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x30
,
(
byte
)
0xe0
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x60
,
(
byte
)
0x42
,
(
byte
)
0x19
,
(
byte
)
0x28
,
(
byte
)
0x34
,
(
byte
)
0x64
,
(
byte
)
0x45
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x27
,
(
byte
)
0x00
,
(
byte
)
0x60
,
(
byte
)
0x70
,
(
byte
)
0x1c
,
(
byte
)
0xcb
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x47
,
(
byte
)
0x92
,
(
byte
)
0x34
,
(
byte
)
0x0d
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x1c
,
(
byte
)
0x49
,
(
byte
)
0xd2
,
(
byte
)
0x34
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0xd0
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0x14
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0xc0
,
(
byte
)
0xd2
,
(
byte
)
0x34
,
(
byte
)
0x51
,
(
byte
)
0x04
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x30
,
(
byte
)
0xe0
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x60
,
(
byte
)
0x42
,
(
byte
)
0x19
,
(
byte
)
0x28
,
(
byte
)
0x34
,
(
byte
)
0x64
,
(
byte
)
0x25
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x05
,
(
byte
)
0x00
,
(
byte
)
0x60
,
(
byte
)
0x30
,
(
byte
)
0x14
,
(
byte
)
0x4d
,
(
byte
)
0x03
,
(
byte
)
0x58
,
(
byte
)
0x16
,
(
byte
)
0xc0
,
(
byte
)
0xb2
,
(
byte
)
0x00
,
(
byte
)
0x9a
,
(
byte
)
0x06
,
(
byte
)
0xd0
,
(
byte
)
0x34
,
(
byte
)
0x80
,
(
byte
)
0xe7
,
(
byte
)
0x01
,
(
byte
)
0x3c
,
(
byte
)
0x11
,
(
byte
)
0x60
,
(
byte
)
0x9a
,
(
byte
)
0x00
,
(
byte
)
0x40
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x40
,
(
byte
)
0x81
,
(
byte
)
0x03
,
(
byte
)
0x00
,
(
byte
)
0x40
,
(
byte
)
0x80
,
(
byte
)
0x0d
,
(
byte
)
0x9a
,
(
byte
)
0x12
,
(
byte
)
0x8b
,
(
byte
)
0x03
,
(
byte
)
0x14
,
(
byte
)
0x1a
,
(
byte
)
0xb2
,
(
byte
)
0x12
,
(
byte
)
0x00
,
(
byte
)
0x88
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x30
,
(
byte
)
0x28
,
(
byte
)
0x8a
,
(
byte
)
0x24
,
(
byte
)
0x59
,
(
byte
)
0x96
,
(
byte
)
0xe7
,
(
byte
)
0x41
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0x14
,
(
byte
)
0xa1
,
(
byte
)
0x69
,
(
byte
)
0x9a
,
(
byte
)
0x26
,
(
byte
)
0x8a
,
(
byte
)
0xf0
,
(
byte
)
0x3c
,
(
byte
)
0xcf
,
(
byte
)
0x13
,
(
byte
)
0x45
,
(
byte
)
0x78
,
(
byte
)
0x9e
,
(
byte
)
0xe7
,
(
byte
)
0x99
,
(
byte
)
0x26
,
(
byte
)
0x44
,
(
byte
)
0xd1
,
(
byte
)
0xf3
,
(
byte
)
0x4c
,
(
byte
)
0x13
,
(
byte
)
0xa2
,
(
byte
)
0xe8
,
(
byte
)
0x79
,
(
byte
)
0xa6
,
(
byte
)
0x09
,
(
byte
)
0xd3
,
(
byte
)
0x14
,
(
byte
)
0x45
,
(
byte
)
0xd3
,
(
byte
)
0x04
,
(
byte
)
0xa2
,
(
byte
)
0x68
,
(
byte
)
0x9a
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x0a
,
(
byte
)
0x1c
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x02
,
(
byte
)
0x6c
,
(
byte
)
0xd0
,
(
byte
)
0x94
,
(
byte
)
0x58
,
(
byte
)
0x1c
,
(
byte
)
0xa0
,
(
byte
)
0xd0
,
(
byte
)
0x90
,
(
byte
)
0x95
,
(
byte
)
0x00
,
(
byte
)
0x40
,
(
byte
)
0x48
,
(
byte
)
0x00
,
(
byte
)
0x80
,
(
byte
)
0x41
,
(
byte
)
0x51
,
(
byte
)
0x2c
,
(
byte
)
0xcb
,
(
byte
)
0xf3
,
(
byte
)
0x44
,
(
byte
)
0x51
,
(
byte
)
0x14
,
(
byte
)
0x4d
,
(
byte
)
0x53
,
(
byte
)
0x55
,
(
byte
)
0x5d
,
(
byte
)
0x17
,
(
byte
)
0x9a
,
(
byte
)
0xe6
,
(
byte
)
0x79
,
(
byte
)
0xa2
,
(
byte
)
0x28
,
(
byte
)
0x8a
,
(
byte
)
0xa6
,
(
byte
)
0xa9
,
(
byte
)
0xaa
,
(
byte
)
0xae
,
(
byte
)
0x0b
,
(
byte
)
0x4d
,
(
byte
)
0xf3
,
(
byte
)
0x3c
,
(
byte
)
0x51
,
(
byte
)
0x14
,
(
byte
)
0x45
,
(
byte
)
0xd3
,
(
byte
)
0x54
,
(
byte
)
0x55
,
(
byte
)
0xd7
,
(
byte
)
0x85
,
(
byte
)
0xe7
,
(
byte
)
0x79
,
(
byte
)
0xa2
,
(
byte
)
0x29
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0xaa
,
(
byte
)
0xaa
,
(
byte
)
0xeb
,
(
byte
)
0xc2
,
(
byte
)
0xf3
,
(
byte
)
0x44
,
(
byte
)
0xd1
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0x53
,
(
byte
)
0x55
,
(
byte
)
0x55
,
(
byte
)
0xd7
,
(
byte
)
0x75
,
(
byte
)
0xe1
,
(
byte
)
0x79
,
(
byte
)
0xa2
,
(
byte
)
0x68
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0xa9
,
(
byte
)
0xaa
,
(
byte
)
0xae
,
(
byte
)
0xeb
,
(
byte
)
0xba
,
(
byte
)
0xf0
,
(
byte
)
0x3c
,
(
byte
)
0x51
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x54
,
(
byte
)
0x55
,
(
byte
)
0xd7
,
(
byte
)
0x95
,
(
byte
)
0x65
,
(
byte
)
0x88
,
(
byte
)
0xa2
,
(
byte
)
0x28
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0x69
,
(
byte
)
0xaa
,
(
byte
)
0xaa
,
(
byte
)
0xeb
,
(
byte
)
0xca
,
(
byte
)
0x32
,
(
byte
)
0x10
,
(
byte
)
0x45
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0x55
,
(
byte
)
0x75
,
(
byte
)
0x5d
,
(
byte
)
0x59
,
(
byte
)
0x06
,
(
byte
)
0xa2
,
(
byte
)
0x68
,
(
byte
)
0x9a
,
(
byte
)
0xaa
,
(
byte
)
0xea
,
(
byte
)
0xba
,
(
byte
)
0xae
,
(
byte
)
0x2b
,
(
byte
)
0xcb
,
(
byte
)
0x40
,
(
byte
)
0x14
,
(
byte
)
0x4d
,
(
byte
)
0x53
,
(
byte
)
0x55
,
(
byte
)
0x5d
,
(
byte
)
0xd7
,
(
byte
)
0x75
,
(
byte
)
0x65
,
(
byte
)
0x19
,
(
byte
)
0x98
,
(
byte
)
0xa6
,
(
byte
)
0x6a
,
(
byte
)
0xaa
,
(
byte
)
0xaa
,
(
byte
)
0xeb
,
(
byte
)
0xca
,
(
byte
)
0xb2
,
(
byte
)
0x2c
,
(
byte
)
0x03
,
(
byte
)
0x4c
,
(
byte
)
0x53
,
(
byte
)
0x55
,
(
byte
)
0x5d
,
(
byte
)
0x57
,
(
byte
)
0x96
,
(
byte
)
0x65
,
(
byte
)
0x19
,
(
byte
)
0xa0
,
(
byte
)
0xaa
,
(
byte
)
0xae
,
(
byte
)
0xeb
,
(
byte
)
0xba
,
(
byte
)
0xb2
,
(
byte
)
0x6c
,
(
byte
)
0xdb
,
(
byte
)
0x00
,
(
byte
)
0x55
,
(
byte
)
0x75
,
(
byte
)
0x5d
,
(
byte
)
0xd7
,
(
byte
)
0x95
,
(
byte
)
0x65
,
(
byte
)
0xdb
,
(
byte
)
0x06
,
(
byte
)
0xb8
,
(
byte
)
0xae
,
(
byte
)
0xeb
,
(
byte
)
0xca
,
(
byte
)
0xb2
,
(
byte
)
0x2c
,
(
byte
)
0xdb
,
(
byte
)
0x36
,
(
byte
)
0x00
,
(
byte
)
0xd7
,
(
byte
)
0x95
,
(
byte
)
0x65
,
(
byte
)
0x59
,
(
byte
)
0xb6
,
(
byte
)
0x6d
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x07
,
(
byte
)
0x0e
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x01
,
(
byte
)
0x46
,
(
byte
)
0xd0
,
(
byte
)
0x49
,
(
byte
)
0x46
,
(
byte
)
0x95
,
(
byte
)
0x45
,
(
byte
)
0xd8
,
(
byte
)
0x68
,
(
byte
)
0xc2
,
(
byte
)
0x85
,
(
byte
)
0x07
,
(
byte
)
0xa0
,
(
byte
)
0xd0
,
(
byte
)
0x90
,
(
byte
)
0x15
,
(
byte
)
0x01
,
(
byte
)
0x40
,
(
byte
)
0x14
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x60
,
(
byte
)
0x8c
,
(
byte
)
0x52
,
(
byte
)
0x8a
,
(
byte
)
0x29
,
(
byte
)
0x65
,
(
byte
)
0x18
,
(
byte
)
0x93
,
(
byte
)
0x50
,
(
byte
)
0x4a
,
(
byte
)
0x09
,
(
byte
)
0x0d
,
(
byte
)
0x63
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0x2a
,
(
byte
)
0xa5
,
(
byte
)
0x92
,
(
byte
)
0x92
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0xa5
,
(
byte
)
0x54
,
(
byte
)
0x12
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0xa9
,
(
byte
)
0x94
,
(
byte
)
0x4a
,
(
byte
)
0x4a
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0x95
,
(
byte
)
0x92
,
(
byte
)
0x51
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0xb5
,
(
byte
)
0x96
,
(
byte
)
0x2a
,
(
byte
)
0x29
,
(
byte
)
0xa9
,
(
byte
)
0x94
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x25
,
(
byte
)
0xa5
,
(
byte
)
0xa4
,
(
byte
)
0x92
,
(
byte
)
0x52
,
(
byte
)
0x2a
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0xec
,
(
byte
)
0xc0
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0xec
,
(
byte
)
0xc0
,
(
byte
)
0x42
,
(
byte
)
0x28
,
(
byte
)
0x34
,
(
byte
)
0x64
,
(
byte
)
0x25
,
(
byte
)
0x00
,
(
byte
)
0x90
,
(
byte
)
0x07
,
(
byte
)
0x00
,
(
byte
)
0x40
,
(
byte
)
0x10
,
(
byte
)
0x82
,
(
byte
)
0x14
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x39
,
(
byte
)
0x27
,
(
byte
)
0xa5
,
(
byte
)
0x54
,
(
byte
)
0x8a
,
(
byte
)
0x31
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x93
,
(
byte
)
0x52
,
(
byte
)
0x2a
,
(
byte
)
0xc5
,
(
byte
)
0x98
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x49
,
(
byte
)
0x29
,
(
byte
)
0x19
,
(
byte
)
0x63
,
(
byte
)
0xcc
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0xa4
,
(
byte
)
0x94
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xe6
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0xc6
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0x29
,
(
byte
)
0x25
,
(
byte
)
0x63
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x94
,
(
byte
)
0xd2
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x83
,
(
byte
)
0x50
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0xa5
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x41
,
(
byte
)
0x28
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x12
,
(
byte
)
0x42
,
(
byte
)
0xe7
,
(
byte
)
0x20
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0xe9
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0x10
,
(
byte
)
0x0a
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x2a
,
(
byte
)
0x70
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x08
,
(
byte
)
0xb0
,
(
byte
)
0x51
,
(
byte
)
0x64
,
(
byte
)
0x73
,
(
byte
)
0x82
,
(
byte
)
0x91
,
(
byte
)
0xa0
,
(
byte
)
0x42
,
(
byte
)
0x43
,
(
byte
)
0x56
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0xa9
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x06
,
(
byte
)
0xc7
,
(
byte
)
0xb1
,
(
byte
)
0x2c
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0xcf
,
(
byte
)
0x13
,
(
byte
)
0x45
,
(
byte
)
0x4b
,
(
byte
)
0x92
,
(
byte
)
0x34
,
(
byte
)
0xcf
,
(
byte
)
0x13
,
(
byte
)
0x3d
,
(
byte
)
0x4f
,
(
byte
)
0x14
,
(
byte
)
0x4d
,
(
byte
)
0xd5
,
(
byte
)
0x92
,
(
byte
)
0x24
,
(
byte
)
0xcf
,
(
byte
)
0x13
,
(
byte
)
0x45
,
(
byte
)
0xcf
,
(
byte
)
0x13
,
(
byte
)
0x4d
,
(
byte
)
0x53
,
(
byte
)
0xe5
,
(
byte
)
0x79
,
(
byte
)
0x9e
,
(
byte
)
0x28
,
(
byte
)
0x8a
,
(
byte
)
0xa2
,
(
byte
)
0x68
,
(
byte
)
0x9a
,
(
byte
)
0xaa
,
(
byte
)
0x4a
,
(
byte
)
0x14
,
(
byte
)
0x45
,
(
byte
)
0x4f
,
(
byte
)
0x14
,
(
byte
)
0x45
,
(
byte
)
0xd1
,
(
byte
)
0x34
,
(
byte
)
0x55
,
(
byte
)
0x95
,
(
byte
)
0x2c
,
(
byte
)
0x8b
,
(
byte
)
0xa2
,
(
byte
)
0x69
,
(
byte
)
0x9a
,
(
byte
)
0xa6
,
(
byte
)
0xaa
,
(
byte
)
0xba
,
(
byte
)
0x2e
,
(
byte
)
0x5b
,
(
byte
)
0x16
,
(
byte
)
0x45
,
(
byte
)
0xd3
,
(
byte
)
0x34
,
(
byte
)
0x4d
,
(
byte
)
0x55
,
(
byte
)
0x75
,
(
byte
)
0x5d
,
(
byte
)
0x98
,
(
byte
)
0xa6
,
(
byte
)
0x28
,
(
byte
)
0xaa
,
(
byte
)
0xaa
,
(
byte
)
0xeb
,
(
byte
)
0xca
,
(
byte
)
0x2e
,
(
byte
)
0x4c
,
(
byte
)
0x53
,
(
byte
)
0x14
,
(
byte
)
0x4d
,
(
byte
)
0xd3
,
(
byte
)
0x75
,
(
byte
)
0x65
,
(
byte
)
0x19
,
(
byte
)
0xb2
,
(
byte
)
0xad
,
(
byte
)
0x9a
,
(
byte
)
0xaa
,
(
byte
)
0xea
,
(
byte
)
0xba
,
(
byte
)
0xb2
,
(
byte
)
0x0d
,
(
byte
)
0xdb
,
(
byte
)
0x36
,
(
byte
)
0x4d
,
(
byte
)
0x55
,
(
byte
)
0x75
,
(
byte
)
0x5d
,
(
byte
)
0x59
,
(
byte
)
0x06
,
(
byte
)
0xae
,
(
byte
)
0xeb
,
(
byte
)
0xba
,
(
byte
)
0xb2
,
(
byte
)
0x6c
,
(
byte
)
0xeb
,
(
byte
)
0xc0
,
(
byte
)
0x75
,
(
byte
)
0x5d
,
(
byte
)
0x57
,
(
byte
)
0x96
,
(
byte
)
0x6d
,
(
byte
)
0x5d
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x82
,
(
byte
)
0x03
,
(
byte
)
0x00
,
(
byte
)
0x50
,
(
byte
)
0x81
,
(
byte
)
0x0d
,
(
byte
)
0xab
,
(
byte
)
0x23
,
(
byte
)
0x9c
,
(
byte
)
0x14
,
(
byte
)
0x8d
,
(
byte
)
0x05
,
(
byte
)
0x16
,
(
byte
)
0x1a
,
(
byte
)
0xb2
,
(
byte
)
0x12
,
(
byte
)
0x00
,
(
byte
)
0xc8
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x20
,
(
byte
)
0x08
,
(
byte
)
0x41
,
(
byte
)
0x48
,
(
byte
)
0x29
,
(
byte
)
0x85
,
(
byte
)
0x90
,
(
byte
)
0x52
,
(
byte
)
0x0a
,
(
byte
)
0x21
,
(
byte
)
0xa5
,
(
byte
)
0x14
,
(
byte
)
0x42
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0x84
,
(
byte
)
0x04
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x0c
,
(
byte
)
0x38
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x04
,
(
byte
)
0x98
,
(
byte
)
0x50
,
(
byte
)
0x06
,
(
byte
)
0x0a
,
(
byte
)
0x0d
,
(
byte
)
0x59
,
(
byte
)
0x09
,
(
byte
)
0x00
,
(
byte
)
0xa4
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x84
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x9c
,
(
byte
)
0x73
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0xb1
,
(
byte
)
0x2b
,
(
byte
)
0x1c
,
(
byte
)
0x00
,
(
byte
)
0x76
,
(
byte
)
0x22
,
(
byte
)
0x6c
,
(
byte
)
0x58
,
(
byte
)
0x1d
,
(
byte
)
0xe1
,
(
byte
)
0xa4
,
(
byte
)
0x68
,
(
byte
)
0x2c
,
(
byte
)
0xb0
,
(
byte
)
0xd0
,
(
byte
)
0x90
,
(
byte
)
0x95
,
(
byte
)
0x00
,
(
byte
)
0x40
,
(
byte
)
0x38
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x60
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xce
,
(
byte
)
0x59
,
(
byte
)
0xac
,
(
byte
)
0xb5
,
(
byte
)
0xd6
,
(
byte
)
0x5a
,
(
byte
)
0x2b
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x92
,
(
byte
)
0x50
,
(
byte
)
0x6b
,
(
byte
)
0xad
,
(
byte
)
0xb5
,
(
byte
)
0xd6
,
(
byte
)
0x9a
,
(
byte
)
0x29
,
(
byte
)
0xa4
,
(
byte
)
0x94
,
(
byte
)
0x84
,
(
byte
)
0x16
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x98
,
(
byte
)
0x31
,
(
byte
)
0x08
,
(
byte
)
0x29
,
(
byte
)
0xb5
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x8c
,
(
byte
)
0x39
,
(
byte
)
0x47
,
(
byte
)
0x2d
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xb6
,
(
byte
)
0x56
,
(
byte
)
0x4a
,
(
byte
)
0x6c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0xb1
,
(
byte
)
0xb5
,
(
byte
)
0x52
,
(
byte
)
0x62
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x16
,
(
byte
)
0x5b
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xb6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xb6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x6c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x18
,
(
byte
)
0x63
,
(
byte
)
0x2c
,
(
byte
)
0x00
,
(
byte
)
0xc0
,
(
byte
)
0xe4
,
(
byte
)
0xc1
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x2a
,
(
byte
)
0xc1
,
(
byte
)
0xc6
,
(
byte
)
0x19
,
(
byte
)
0x56
,
(
byte
)
0x92
,
(
byte
)
0xce
,
(
byte
)
0x0a
,
(
byte
)
0x47
,
(
byte
)
0x83
,
(
byte
)
0x0b
,
(
byte
)
0x0d
,
(
byte
)
0x59
,
(
byte
)
0x09
,
(
byte
)
0x00
,
(
byte
)
0xe4
,
(
byte
)
0x06
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0xc6
,
(
byte
)
0x28
,
(
byte
)
0xc5
,
(
byte
)
0x98
,
(
byte
)
0x63
,
(
byte
)
0xce
,
(
byte
)
0x41
,
(
byte
)
0x08
,
(
byte
)
0xa1
,
(
byte
)
0x94
,
(
byte
)
0x12
,
(
byte
)
0x4a
,
(
byte
)
0x49
,
(
byte
)
0xad
,
(
byte
)
0x75
,
(
byte
)
0xce
,
(
byte
)
0x39
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0x49
,
(
byte
)
0xa9
,
(
byte
)
0xb4
,
(
byte
)
0x94
,
(
byte
)
0x62
,
(
byte
)
0xca
,
(
byte
)
0x98
,
(
byte
)
0x73
,
(
byte
)
0xce
,
(
byte
)
0x41
,
(
byte
)
0x08
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x12
,
(
byte
)
0x4a
,
(
byte
)
0x49
,
(
byte
)
0xa9
,
(
byte
)
0xa5
,
(
byte
)
0xd4
,
(
byte
)
0x39
,
(
byte
)
0xe7
,
(
byte
)
0x20
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x5a
,
(
byte
)
0x6a
,
(
byte
)
0xad
,
(
byte
)
0x73
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x08
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0xa5
,
(
byte
)
0xd4
,
(
byte
)
0x52
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0x2a
,
(
byte
)
0x29
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x6b
,
(
byte
)
0xad
,
(
byte
)
0xa5
,
(
byte
)
0x10
,
(
byte
)
0x42
,
(
byte
)
0x28
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0xa5
,
(
byte
)
0xd4
,
(
byte
)
0x5a
,
(
byte
)
0x8b
,
(
byte
)
0xa1
,
(
byte
)
0x94
,
(
byte
)
0x90
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0x25
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x49
,
(
byte
)
0x2d
,
(
byte
)
0xb5
,
(
byte
)
0x96
,
(
byte
)
0x5a
,
(
byte
)
0x2a
,
(
byte
)
0xa1
,
(
byte
)
0x94
,
(
byte
)
0x54
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x6b
,
(
byte
)
0xa9
,
(
byte
)
0xb5
,
(
byte
)
0x56
,
(
byte
)
0x4a
,
(
byte
)
0x49
,
(
byte
)
0x25
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0xa5
,
(
byte
)
0xd4
,
(
byte
)
0x62
,
(
byte
)
0x6b
,
(
byte
)
0x29
,
(
byte
)
0x94
,
(
byte
)
0x92
,
(
byte
)
0x52
,
(
byte
)
0x49
,
(
byte
)
0x29
,
(
byte
)
0xb5
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0xad
,
(
byte
)
0xc5
,
(
byte
)
0xd8
,
(
byte
)
0x62
,
(
byte
)
0x29
,
(
byte
)
0xad
,
(
byte
)
0xa4
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0xa5
,
(
byte
)
0xd6
,
(
byte
)
0x52
,
(
byte
)
0x6c
,
(
byte
)
0xad
,
(
byte
)
0xb5
,
(
byte
)
0xd8
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0xa5
,
(
byte
)
0x96
,
(
byte
)
0x5a
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0xb5
,
(
byte
)
0x16
,
(
byte
)
0x5b
,
(
byte
)
0x6a
,
(
byte
)
0x2d
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x4b
,
(
byte
)
0x29
,
(
byte
)
0xa5
,
(
byte
)
0x96
,
(
byte
)
0x52
,
(
byte
)
0x4b
,
(
byte
)
0x2d
,
(
byte
)
0xc6
,
(
byte
)
0xd6
,
(
byte
)
0x5a
,
(
byte
)
0x4b
,
(
byte
)
0x29
,
(
byte
)
0xa5
,
(
byte
)
0xd4
,
(
byte
)
0x52
,
(
byte
)
0x6a
,
(
byte
)
0xa9
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x6c
,
(
byte
)
0xad
,
(
byte
)
0xb5
,
(
byte
)
0x98
,
(
byte
)
0x52
,
(
byte
)
0x6a
,
(
byte
)
0x2d
,
(
byte
)
0xa5
,
(
byte
)
0xd4
,
(
byte
)
0x52
,
(
byte
)
0x6b
,
(
byte
)
0x2d
,
(
byte
)
0xb5
,
(
byte
)
0xd8
,
(
byte
)
0x52
,
(
byte
)
0x6a
,
(
byte
)
0x2d
,
(
byte
)
0xb5
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x6b
,
(
byte
)
0xa9
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x5a
,
(
byte
)
0x6b
,
(
byte
)
0x2d
,
(
byte
)
0xb6
,
(
byte
)
0xd8
,
(
byte
)
0x5a
,
(
byte
)
0x6b
,
(
byte
)
0x29
,
(
byte
)
0xb5
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x4a
,
(
byte
)
0xa9
,
(
byte
)
0xb5
,
(
byte
)
0x16
,
(
byte
)
0x5b
,
(
byte
)
0x8a
,
(
byte
)
0xb1
,
(
byte
)
0xb5
,
(
byte
)
0xd4
,
(
byte
)
0x4a
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0xb5
,
(
byte
)
0xd4
,
(
byte
)
0x5a
,
(
byte
)
0x6a
,
(
byte
)
0x2d
,
(
byte
)
0xb6
,
(
byte
)
0x16
,
(
byte
)
0x5b
,
(
byte
)
0x6b
,
(
byte
)
0xad
,
(
byte
)
0xa5
,
(
byte
)
0xd6
,
(
byte
)
0x5a
,
(
byte
)
0x6a
,
(
byte
)
0x29
,
(
byte
)
0xa5
,
(
byte
)
0x16
,
(
byte
)
0x5b
,
(
byte
)
0x8c
,
(
byte
)
0x31
,
(
byte
)
0xc6
,
(
byte
)
0x16
,
(
byte
)
0x63
,
(
byte
)
0x6b
,
(
byte
)
0x31
,
(
byte
)
0xa5
,
(
byte
)
0x94
,
(
byte
)
0x52
,
(
byte
)
0x4b
,
(
byte
)
0xa9
,
(
byte
)
0xa5
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x80
,
(
byte
)
0x0e
,
(
byte
)
0x1c
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x02
,
(
byte
)
0x8c
,
(
byte
)
0xa8
,
(
byte
)
0xb4
,
(
byte
)
0x10
,
(
byte
)
0x3b
,
(
byte
)
0xcd
,
(
byte
)
0xb8
,
(
byte
)
0xf2
,
(
byte
)
0x08
,
(
byte
)
0x1c
,
(
byte
)
0x51
,
(
byte
)
0xc8
,
(
byte
)
0x30
,
(
byte
)
0x01
,
(
byte
)
0x15
,
(
byte
)
0x1a
,
(
byte
)
0xb2
,
(
byte
)
0x12
,
(
byte
)
0x00
,
(
byte
)
0x20
,
(
byte
)
0x03
,
(
byte
)
0x00
,
(
byte
)
0x20
,
(
byte
)
0x90
,
(
byte
)
0x69
,
(
byte
)
0x92
,
(
byte
)
0x39
,
(
byte
)
0x49
,
(
byte
)
0xa9
,
(
byte
)
0x11
,
(
byte
)
0x26
,
(
byte
)
0x39
,
(
byte
)
0xc5
,
(
byte
)
0xa0
,
(
byte
)
0x94
,
(
byte
)
0xe6
,
(
byte
)
0x9c
,
(
byte
)
0x53
,
(
byte
)
0x4a
,
(
byte
)
0x29
,
(
byte
)
0xa5
,
(
byte
)
0x34
,
(
byte
)
0x44
,
(
byte
)
0x96
,
(
byte
)
0x64
,
(
byte
)
0x90
,
(
byte
)
0x62
,
(
byte
)
0x50
,
(
byte
)
0x1d
,
(
byte
)
0x99
,
(
byte
)
0x8c
,
(
byte
)
0x39
,
(
byte
)
0x49
,
(
byte
)
0x39
,
(
byte
)
0x43
,
(
byte
)
0xa4
,
(
byte
)
0x31
,
(
byte
)
0xa4
,
(
byte
)
0x20
,
(
byte
)
0xf5
,
(
byte
)
0x4c
,
(
byte
)
0x91
,
(
byte
)
0xc7
,
(
byte
)
0x94
,
(
byte
)
0x62
,
(
byte
)
0x10
,
(
byte
)
0x43
,
(
byte
)
0x48
,
(
byte
)
0x2a
,
(
byte
)
0x74
,
(
byte
)
0x8a
,
(
byte
)
0x39
,
(
byte
)
0x6c
,
(
byte
)
0x35
,
(
byte
)
0xf9
,
(
byte
)
0x58
,
(
byte
)
0x42
,
(
byte
)
0x07
,
(
byte
)
0xb1
,
(
byte
)
0x06
,
(
byte
)
0x65
,
(
byte
)
0x8c
,
(
byte
)
0x70
,
(
byte
)
0x29
,
(
byte
)
0xc5
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x08
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x04
,
(
byte
)
0x84
,
(
byte
)
0x04
,
(
byte
)
0x00
,
(
byte
)
0x18
,
(
byte
)
0x20
,
(
byte
)
0x28
,
(
byte
)
0x98
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x06
,
(
byte
)
0x07
,
(
byte
)
0x08
,
(
byte
)
0x23
,
(
byte
)
0x07
,
(
byte
)
0x02
,
(
byte
)
0x1d
,
(
byte
)
0x01
,
(
byte
)
0x04
,
(
byte
)
0x0e
,
(
byte
)
0x6d
,
(
byte
)
0x00
,
(
byte
)
0x80
,
(
byte
)
0x81
,
(
byte
)
0x08
,
(
byte
)
0x99
,
(
byte
)
0x09
,
(
byte
)
0x0c
,
(
byte
)
0x0a
,
(
byte
)
0xa1
,
(
byte
)
0xc1
,
(
byte
)
0x41
,
(
byte
)
0x26
,
(
byte
)
0x00
,
(
byte
)
0x3c
,
(
byte
)
0x40
,
(
byte
)
0x44
,
(
byte
)
0x48
,
(
byte
)
0x05
,
(
byte
)
0x00
,
(
byte
)
0x89
,
(
byte
)
0x09
,
(
byte
)
0x8a
,
(
byte
)
0xd2
,
(
byte
)
0x85
,
(
byte
)
0x2e
,
(
byte
)
0x08
,
(
byte
)
0x21
,
(
byte
)
0x82
,
(
byte
)
0x74
,
(
byte
)
0x11
,
(
byte
)
0x64
,
(
byte
)
0xf1
,
(
byte
)
0xc0
,
(
byte
)
0x85
,
(
byte
)
0x13
,
(
byte
)
0x37
,
(
byte
)
0x9e
,
(
byte
)
0xb8
,
(
byte
)
0xe1
,
(
byte
)
0x84
,
(
byte
)
0x0e
,
(
byte
)
0x6d
,
(
byte
)
0x20
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x20
,
(
byte
)
0x00
,
(
byte
)
0xf0
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x90
,
(
byte
)
0x50
,
(
byte
)
0x00
,
(
byte
)
0x11
,
(
byte
)
0x11
,
(
byte
)
0xd1
,
(
byte
)
0xcc
,
(
byte
)
0x55
,
(
byte
)
0x58
,
(
byte
)
0x5c
,
(
byte
)
0x60
,
(
byte
)
0x64
,
(
byte
)
0x68
,
(
byte
)
0x6c
,
(
byte
)
0x70
,
(
byte
)
0x74
,
(
byte
)
0x78
,
(
byte
)
0x7c
,
(
byte
)
0x80
,
(
byte
)
0x84
,
(
byte
)
0x08
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x00
,
(
byte
)
0x7c
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x24
,
(
byte
)
0x22
,
(
byte
)
0x40
,
(
byte
)
0x44
,
(
byte
)
0x44
,
(
byte
)
0x34
,
(
byte
)
0x73
,
(
byte
)
0x15
,
(
byte
)
0x16
,
(
byte
)
0x17
,
(
byte
)
0x18
,
(
byte
)
0x19
,
(
byte
)
0x1a
,
(
byte
)
0x1b
,
(
byte
)
0x1c
,
(
byte
)
0x1d
,
(
byte
)
0x1e
,
(
byte
)
0x1f
,
(
byte
)
0x20
,
(
byte
)
0x21
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x80
,
(
byte
)
0x00
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x20
,
(
byte
)
0x80
,
(
byte
)
0x00
,
(
byte
)
0x04
,
(
byte
)
0x04
,
(
byte
)
0x04
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x04
,
(
byte
)
0x04
};
}
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/VorbisBitArrayTest.java
0 → 100644
View file @
89ce1cce
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer
.
extractor
.
ogg
;
import
com.google.android.exoplayer.ParserException
;
import
com.google.android.exoplayer.util.ParsableBitArray
;
import
junit.framework.TestCase
;
/**
* Unit test for {@link VorbisBitArray}.
*/
public
final
class
VorbisBitArrayTest
extends
TestCase
{
public
void
testReadBit
()
throws
ParserException
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
new
byte
[]{
(
byte
)
0x5c
,
0x50
});
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
try
{
assertFalse
(
bitArray
.
readBit
());
fail
();
}
catch
(
IllegalStateException
e
)
{
/* ignored */
}
}
public
void
testSkipBits
()
throws
ParserException
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
new
byte
[]{
(
byte
)
0xF0
,
0x0F
});
bitArray
.
skipBits
(
10
);
assertEquals
(
10
,
bitArray
.
getPosition
());
assertTrue
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
bitArray
.
skipBits
(
1
);
assertEquals
(
14
,
bitArray
.
getPosition
());
assertFalse
(
bitArray
.
readBit
());
assertFalse
(
bitArray
.
readBit
());
try
{
bitArray
.
readBit
();
fail
();
}
catch
(
IllegalStateException
e
)
{
// ignored
}
}
public
void
testSkipBitsThrowsErrorIfEOB
()
throws
ParserException
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
new
byte
[]{
(
byte
)
0xF0
,
0x0F
});
try
{
bitArray
.
skipBits
(
17
);
fail
();
}
catch
(
IllegalStateException
e
)
{
/* ignored */
}
}
public
void
testGetPosition
()
throws
Exception
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
new
byte
[]{
(
byte
)
0xF0
,
0x0F
});
assertEquals
(
0
,
bitArray
.
getPosition
());
bitArray
.
readBit
();
assertEquals
(
1
,
bitArray
.
getPosition
());
bitArray
.
readBit
();
bitArray
.
readBit
();
bitArray
.
skipBits
(
4
);
assertEquals
(
7
,
bitArray
.
getPosition
());
}
public
void
testSetPosition
()
throws
Exception
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
new
byte
[]{
(
byte
)
0xF0
,
0x0F
});
assertEquals
(
0
,
bitArray
.
getPosition
());
bitArray
.
setPosition
(
4
);
assertEquals
(
4
,
bitArray
.
getPosition
());
bitArray
.
setPosition
(
15
);
assertFalse
(
bitArray
.
readBit
());
try
{
bitArray
.
readBit
();
fail
();
}
catch
(
IllegalStateException
e
)
{
/* ignored */
}
}
public
void
testSetPositionIllegalPositions
()
throws
Exception
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
new
byte
[]{
(
byte
)
0xF0
,
0x0F
});
try
{
bitArray
.
setPosition
(
16
);
fail
();
}
catch
(
IllegalArgumentException
e
)
{
assertEquals
(
0
,
bitArray
.
getPosition
());
}
try
{
bitArray
.
setPosition
(-
1
);
fail
();
}
catch
(
IllegalArgumentException
e
)
{
assertEquals
(
0
,
bitArray
.
getPosition
());
}
}
public
void
testReadInt32
()
throws
ParserException
{
byte
[]
data
=
{(
byte
)
0xF0
,
0x0F
,
(
byte
)
0xF0
,
0x0F
};
VorbisBitArray
lsb
=
new
VorbisBitArray
(
data
);
assertEquals
(
0x0FF00FF0
,
lsb
.
readBits
(
32
));
data
=
new
byte
[]{
0x0F
,
(
byte
)
0xF0
,
0x0F
,
(
byte
)
0xF0
};
lsb
=
new
VorbisBitArray
(
data
);
assertEquals
(
0xF00FF00F
,
lsb
.
readBits
(
32
));
}
public
void
testReadBits
()
throws
Exception
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
new
byte
[]{
(
byte
)
0x03
,
0x22
});
assertEquals
(
3
,
bitArray
.
readBits
(
2
));
bitArray
.
skipBits
(
6
);
assertEquals
(
2
,
bitArray
.
readBits
(
2
));
bitArray
.
skipBits
(
2
);
assertEquals
(
2
,
bitArray
.
readBits
(
2
));
bitArray
.
reset
();
assertEquals
(
0x2203
,
bitArray
.
readBits
(
16
));
}
public
void
testRead4BitsBeyondBoundary
()
throws
Exception
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
new
byte
[]{
0x2e
,
0x10
});
assertEquals
(
0x2e
,
bitArray
.
readBits
(
7
));
assertEquals
(
7
,
bitArray
.
getPosition
());
assertEquals
(
0x0
,
bitArray
.
readBits
(
4
));
}
public
void
testReadBitsBeyondByteBoundaries
()
throws
Exception
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
new
byte
[]{
(
byte
)
0xFF
,
(
byte
)
0x0F
,
(
byte
)
0xFF
,
(
byte
)
0x0F
});
assertEquals
(
0x0FFF0FFF
,
bitArray
.
readBits
(
32
));
bitArray
.
reset
();
bitArray
.
skipBits
(
4
);
assertEquals
(
0xF0FF
,
bitArray
.
readBits
(
16
));
bitArray
.
reset
();
bitArray
.
skipBits
(
6
);
assertEquals
(
0xc3F
,
bitArray
.
readBits
(
12
));
bitArray
.
reset
();
bitArray
.
skipBits
(
6
);
assertTrue
(
bitArray
.
readBit
());
assertTrue
(
bitArray
.
readBit
());
assertEquals
(
24
,
bitArray
.
bitsLeft
());
bitArray
.
reset
();
bitArray
.
skipBits
(
10
);
assertEquals
(
3
,
bitArray
.
readBits
(
5
));
assertEquals
(
15
,
bitArray
.
getPosition
());
}
public
void
testReadBitsIllegalLengths
()
throws
Exception
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
new
byte
[]{
(
byte
)
0x03
,
0x22
,
0x30
});
// reading zero bits gets 0 without advancing position
// (like a zero-bit read is defined to yield zer0)
assertEquals
(
0
,
bitArray
.
readBits
(
0
));
assertEquals
(
0
,
bitArray
.
getPosition
());
bitArray
.
readBit
();
assertEquals
(
1
,
bitArray
.
getPosition
());
try
{
bitArray
.
readBits
(
24
);
fail
();
}
catch
(
IllegalStateException
e
)
{
assertEquals
(
1
,
bitArray
.
getPosition
());
}
}
public
void
testLimit
()
throws
ParserException
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
new
byte
[]{
(
byte
)
0xc0
,
0x02
},
1
);
try
{
bitArray
.
skipBits
(
9
);
fail
();
}
catch
(
IllegalStateException
e
)
{
assertEquals
(
0
,
bitArray
.
getPosition
());
}
try
{
bitArray
.
readBits
(
9
);
fail
();
}
catch
(
IllegalStateException
e
)
{
assertEquals
(
0
,
bitArray
.
getPosition
());
}
bitArray
.
readBits
(
8
);
assertEquals
(
8
,
bitArray
.
getPosition
());
try
{
bitArray
.
readBit
();
fail
();
}
catch
(
IllegalStateException
e
)
{
assertEquals
(
8
,
bitArray
.
getPosition
());
}
}
public
void
testBitsLeft
()
throws
ParserException
{
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
new
byte
[]{
(
byte
)
0xc0
,
0x02
});
assertEquals
(
16
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
skipBits
(
1
);
assertEquals
(
15
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
skipBits
(
3
);
assertEquals
(
12
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
setPosition
(
6
);
assertEquals
(
10
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
readBit
();
assertEquals
(
9
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
readBits
(
1
);
assertEquals
(
8
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
readBits
(
4
);
assertEquals
(
4
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
bitArray
.
readBits
(
4
);
assertEquals
(
0
,
bitArray
.
bitsLeft
());
assertEquals
(
bitArray
.
limit
(),
bitArray
.
getPosition
()
+
bitArray
.
bitsLeft
());
try
{
bitArray
.
readBit
();
fail
();
}
catch
(
IllegalStateException
e
)
{
assertEquals
(
0
,
bitArray
.
bitsLeft
());
}
}
public
void
testReadBitCompareWithMSb
()
throws
ParserException
{
byte
[]
data
=
{
0x0F
};
VorbisBitArray
lsb
=
new
VorbisBitArray
(
data
);
ParsableBitArray
msb
=
new
ParsableBitArray
(
data
);
assertEquals
(
lsb
.
readBit
(),
!
msb
.
readBit
());
assertEquals
(
lsb
.
readBit
(),
!
msb
.
readBit
());
assertEquals
(
lsb
.
readBit
(),
!
msb
.
readBit
());
assertEquals
(
lsb
.
readBit
(),
!
msb
.
readBit
());
assertEquals
(
lsb
.
readBit
(),
!
msb
.
readBit
());
assertEquals
(
lsb
.
readBit
(),
!
msb
.
readBit
());
assertEquals
(
lsb
.
readBit
(),
!
msb
.
readBit
());
assertEquals
(
lsb
.
readBit
(),
!
msb
.
readBit
());
}
public
void
testReadBitsCompareWithMSb
()
throws
ParserException
{
byte
[]
data
=
{
0x0F
};
VorbisBitArray
lsb
=
new
VorbisBitArray
(
data
);
ParsableBitArray
msb
=
new
ParsableBitArray
(
data
);
assertEquals
(
15
,
lsb
.
readBits
(
4
));
assertEquals
(
lsb
.
readBits
(
4
),
msb
.
readBits
(
4
));
assertEquals
(
15
,
msb
.
readBits
(
4
));
}
public
void
testReadBitsCompareWithMSbBeyondByteBoundary
()
throws
ParserException
{
byte
[]
data
=
{(
byte
)
0xF0
,
0x0F
};
VorbisBitArray
lsb
=
new
VorbisBitArray
(
data
);
ParsableBitArray
msb
=
new
ParsableBitArray
(
data
);
assertEquals
(
0x00
,
lsb
.
readBits
(
4
));
assertEquals
(
0x0F
,
msb
.
readBits
(
4
));
assertEquals
(
0xFF
,
lsb
.
readBits
(
8
));
assertEquals
(
0x00
,
msb
.
readBits
(
8
));
assertEquals
(
0x00
,
lsb
.
readBits
(
4
));
assertEquals
(
0x0F
,
msb
.
readBits
(
4
));
}
}
library/src/androidTest/java/com/google/android/exoplayer/extractor/ogg/VorbisUtilTest.java
0 → 100644
View file @
89ce1cce
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer
.
extractor
.
ogg
;
import
com.google.android.exoplayer.ParserException
;
import
com.google.android.exoplayer.util.ParsableByteArray
;
import
junit.framework.TestCase
;
/**
* Unit test for {@link VorbisUtil}.
*/
public
final
class
VorbisUtilTest
extends
TestCase
{
public
void
testILog
()
throws
Exception
{
assertEquals
(
0
,
VorbisUtil
.
iLog
(
0
));
assertEquals
(
1
,
VorbisUtil
.
iLog
(
1
));
assertEquals
(
2
,
VorbisUtil
.
iLog
(
2
));
assertEquals
(
2
,
VorbisUtil
.
iLog
(
3
));
assertEquals
(
3
,
VorbisUtil
.
iLog
(
4
));
assertEquals
(
3
,
VorbisUtil
.
iLog
(
5
));
assertEquals
(
4
,
VorbisUtil
.
iLog
(
8
));
assertEquals
(
0
,
VorbisUtil
.
iLog
(-
1
));
assertEquals
(
0
,
VorbisUtil
.
iLog
(-
122
));
}
public
void
testReadBits
()
throws
Exception
{
assertEquals
(
0
,
VorbisUtil
.
readBits
((
byte
)
0x00
,
2
,
2
));
assertEquals
(
1
,
VorbisUtil
.
readBits
((
byte
)
0x02
,
1
,
1
));
assertEquals
(
15
,
VorbisUtil
.
readBits
((
byte
)
0xF0
,
4
,
4
));
assertEquals
(
1
,
VorbisUtil
.
readBits
((
byte
)
0x80
,
1
,
7
));
}
public
void
testReadIdHeader
()
throws
Exception
{
byte
[]
data
=
TestData
.
getIdentificationHeaderData
();
ParsableByteArray
headerData
=
new
ParsableByteArray
(
data
,
data
.
length
);
VorbisUtil
.
VorbisIdHeader
vorbisIdHeader
=
VorbisUtil
.
readVorbisIdentificationHeader
(
headerData
);
assertEquals
(
22050
,
vorbisIdHeader
.
sampleRate
);
assertEquals
(
0
,
vorbisIdHeader
.
version
);
assertTrue
(
vorbisIdHeader
.
framingFlag
);
assertEquals
(
2
,
vorbisIdHeader
.
channels
);
assertEquals
(
512
,
vorbisIdHeader
.
blockSize0
);
assertEquals
(
1024
,
vorbisIdHeader
.
blockSize1
);
assertEquals
(-
1
,
vorbisIdHeader
.
bitrateMax
);
assertEquals
(-
1
,
vorbisIdHeader
.
bitrateMin
);
assertEquals
(
66666
,
vorbisIdHeader
.
bitrateNominal
);
assertEquals
(
66666
,
vorbisIdHeader
.
getApproximateBitrate
());
}
public
void
testReadCommentHeader
()
throws
ParserException
{
byte
[]
data
=
TestData
.
getCommentHeaderDataUTF8
();
ParsableByteArray
headerData
=
new
ParsableByteArray
(
data
,
data
.
length
);
VorbisUtil
.
CommentHeader
commentHeader
=
VorbisUtil
.
readVorbisCommentHeader
(
headerData
);
assertEquals
(
"Xiph.Org libVorbis I 20120203 (Omnipresent)"
,
commentHeader
.
vendor
);
assertEquals
(
3
,
commentHeader
.
comments
.
length
);
assertEquals
(
"ALBUM=äö"
,
commentHeader
.
comments
[
0
]);
assertEquals
(
"TITLE=A sample song"
,
commentHeader
.
comments
[
1
]);
assertEquals
(
"ARTIST=Google"
,
commentHeader
.
comments
[
2
]);
}
public
void
testReadVorbisModes
()
throws
ParserException
{
byte
[]
data
=
TestData
.
getSetupHeaderData
();
ParsableByteArray
headerData
=
new
ParsableByteArray
(
data
,
data
.
length
);
VorbisUtil
.
Mode
[]
modes
=
VorbisUtil
.
readVorbisModes
(
headerData
,
2
);
assertEquals
(
2
,
modes
.
length
);
assertEquals
(
false
,
modes
[
0
].
blockFlag
);
assertEquals
(
0
,
modes
[
0
].
mapping
);
assertEquals
(
0
,
modes
[
0
].
transformType
);
assertEquals
(
0
,
modes
[
0
].
windowType
);
assertEquals
(
true
,
modes
[
1
].
blockFlag
);
assertEquals
(
1
,
modes
[
1
].
mapping
);
assertEquals
(
0
,
modes
[
1
].
transformType
);
assertEquals
(
0
,
modes
[
1
].
windowType
);
}
}
library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java
View file @
89ce1cce
...
...
@@ -154,6 +154,13 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourceRe
}
catch
(
ClassNotFoundException
e
)
{
// Extractor not found.
}
try
{
DEFAULT_EXTRACTOR_CLASSES
.
add
(
Class
.
forName
(
"com.google.android.exoplayer.extractor.ogg.OggVorbisExtractor"
)
.
asSubclass
(
Extractor
.
class
));
}
catch
(
ClassNotFoundException
e
)
{
// Extractor not found.
}
}
private
final
ExtractorHolder
extractorHolder
;
...
...
library/src/main/java/com/google/android/exoplayer/extractor/ogg/OggReader.java
0 → 100644
View file @
89ce1cce
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer
.
extractor
.
ogg
;
import
com.google.android.exoplayer.ParserException
;
import
com.google.android.exoplayer.extractor.ExtractorInput
;
import
com.google.android.exoplayer.util.Assertions
;
import
com.google.android.exoplayer.util.ParsableByteArray
;
import
com.google.android.exoplayer.util.Util
;
import
java.io.IOException
;
/**
* Reads OGG packets from an {@link ExtractorInput}.
*/
/* package */
final
class
OggReader
{
private
static
final
String
CAPTURE_PATTERN_PAGE
=
"OggS"
;
private
final
PageHeader
pageHeader
=
new
PageHeader
();
private
final
ParsableByteArray
headerArray
=
new
ParsableByteArray
(
27
+
255
);
private
int
currentSegmentIndex
=
-
1
;
/**
* Resets this reader.
*/
public
void
reset
()
{
pageHeader
.
reset
();
headerArray
.
reset
();
currentSegmentIndex
=
-
1
;
}
/**
* Reads the next packet of the ogg stream. In case of an {@code IOException} the caller must make
* sure to pass the same instance of {@code ParsableByteArray} to this method again so this reader
* can resume properly from an error while reading a continued packet spanned across multiple
* pages.
*
* @param input the {@link ExtractorInput} to read data from.
* @param packetArray the {@link ParsableByteArray} to write the packet data into.
* @return {@code true} if the read was successful. {@code false} if the end of the input was
* encountered having read no data.
* @throws IOException thrown if reading from the input fails.
* @throws InterruptedException thrown if interrupted while reading from input.
*/
public
boolean
readPacket
(
ExtractorInput
input
,
ParsableByteArray
packetArray
)
throws
IOException
,
InterruptedException
{
Assertions
.
checkState
(
input
!=
null
&&
packetArray
!=
null
);
boolean
packetComplete
=
false
;
while
(!
packetComplete
)
{
if
(
currentSegmentIndex
<
0
)
{
// We're at the start of a page.
if
(!
populatePageHeader
(
input
,
pageHeader
,
headerArray
,
false
))
{
return
false
;
}
currentSegmentIndex
=
0
;
}
int
packetSize
=
0
;
int
segmentIndex
=
currentSegmentIndex
;
// add up packetSize from laces
while
(
segmentIndex
<
pageHeader
.
pageSegmentCount
)
{
int
segmentLength
=
pageHeader
.
laces
[
segmentIndex
++];
packetSize
+=
segmentLength
;
if
(
segmentLength
!=
255
)
{
// packets end at first lace < 255
break
;
}
}
if
(
packetSize
>
0
)
{
input
.
readFully
(
packetArray
.
data
,
packetArray
.
limit
(),
packetSize
);
packetArray
.
setLimit
(
packetArray
.
limit
()
+
packetSize
);
packetComplete
=
pageHeader
.
laces
[
segmentIndex
-
1
]
!=
255
;
}
// advance now since we are sure reading didn't throw an exception
currentSegmentIndex
=
segmentIndex
==
pageHeader
.
pageSegmentCount
?
-
1
:
segmentIndex
;
}
return
true
;
}
/**
* Returns the {@link OggReader.PageHeader} of the current page. The header might not have been
* populated if the first packet has yet to be read.
* <p>
* Note that there is only a single instance of {@code OggReader.PageHeader} which is mutable.
* The value of the fields might be changed by the reader when reading the stream advances and
* the next page is read (which implies reading and populating the next header).
*
* @return the {@code PageHeader} of the current page or {@code null}.
*/
public
PageHeader
getPageHeader
()
{
return
pageHeader
;
}
/**
* Reads/peeks an Ogg page header and stores the data in the {@code header} object passed
* as argument.
*
* @param input the {@link ExtractorInput} to read from.
* @param header the {@link PageHeader} to read from.
* @param scratch a scratch array temporary use.
* @param peek pass {@code true} if data should only be peeked from current peek position.
* @return {@code true} if the read was successful. {@code false} if the end of the
* input was encountered having read no data.
* @throws IOException thrown if reading data fails or the stream is invalid.
* @throws InterruptedException thrown if thread is interrupted when reading/peeking.
*/
public
static
boolean
populatePageHeader
(
ExtractorInput
input
,
PageHeader
header
,
ParsableByteArray
scratch
,
boolean
peek
)
throws
IOException
,
InterruptedException
{
scratch
.
reset
();
header
.
reset
();
if
(!
input
.
peekFully
(
scratch
.
data
,
0
,
27
,
true
))
{
return
false
;
}
if
(
scratch
.
readUnsignedInt
()
!=
Util
.
getIntegerCodeForString
(
CAPTURE_PATTERN_PAGE
))
{
throw
new
ParserException
(
"expected OggS capture pattern at begin of page"
);
}
header
.
revision
=
scratch
.
readUnsignedByte
();
if
(
header
.
revision
!=
0x00
)
{
throw
new
ParserException
(
"unsupported bit stream revision"
);
}
header
.
type
=
scratch
.
readUnsignedByte
();
header
.
granulePosition
=
scratch
.
readLittleEndianLong
();
header
.
streamSerialNumber
=
scratch
.
readLittleEndianUnsignedInt
();
header
.
pageSequenceNumber
=
scratch
.
readLittleEndianUnsignedInt
();
header
.
pageChecksum
=
scratch
.
readLittleEndianUnsignedInt
();
header
.
pageSegmentCount
=
scratch
.
readUnsignedByte
();
scratch
.
reset
();
// calculate total size of header including laces
header
.
headerSize
=
27
+
header
.
pageSegmentCount
;
input
.
peekFully
(
scratch
.
data
,
0
,
header
.
pageSegmentCount
);
for
(
int
i
=
0
;
i
<
header
.
pageSegmentCount
;
i
++)
{
header
.
laces
[
i
]
=
scratch
.
readUnsignedByte
();
header
.
bodySize
+=
header
.
laces
[
i
];
}
if
(!
peek
)
{
input
.
skipFully
(
header
.
headerSize
);
}
return
true
;
}
/**
* Data object to store header information. Be aware that {@code laces.length} is always 255.
* Instead use {@code pageSegmentCount} to iterate.
*/
public
static
final
class
PageHeader
{
public
int
revision
;
public
int
type
;
public
long
granulePosition
;
public
long
streamSerialNumber
;
public
long
pageSequenceNumber
;
public
long
pageChecksum
;
public
int
pageSegmentCount
;
public
int
headerSize
;
public
int
bodySize
;
public
int
[]
laces
=
new
int
[
255
];
/**
* Resets all primitive member fields to zero.
*/
public
void
reset
()
{
revision
=
0
;
type
=
0
;
granulePosition
=
0
;
streamSerialNumber
=
0
;
pageSequenceNumber
=
0
;
pageChecksum
=
0
;
pageSegmentCount
=
0
;
headerSize
=
0
;
bodySize
=
0
;
}
}
}
library/src/main/java/com/google/android/exoplayer/extractor/ogg/OggVorbisExtractor.java
0 → 100644
View file @
89ce1cce
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer
.
extractor
.
ogg
;
import
com.google.android.exoplayer.C
;
import
com.google.android.exoplayer.MediaFormat
;
import
com.google.android.exoplayer.ParserException
;
import
com.google.android.exoplayer.extractor.Extractor
;
import
com.google.android.exoplayer.extractor.ExtractorInput
;
import
com.google.android.exoplayer.extractor.ExtractorOutput
;
import
com.google.android.exoplayer.extractor.PositionHolder
;
import
com.google.android.exoplayer.extractor.SeekMap
;
import
com.google.android.exoplayer.extractor.TrackOutput
;
import
com.google.android.exoplayer.extractor.ogg.VorbisUtil.Mode
;
import
com.google.android.exoplayer.util.MimeTypes
;
import
com.google.android.exoplayer.util.ParsableByteArray
;
import
android.util.Log
;
import
java.io.IOException
;
import
java.util.ArrayList
;
/**
* {@link Extractor} to extract Vorbis data out of Ogg byte stream.
*/
public
final
class
OggVorbisExtractor
implements
Extractor
{
private
static
final
String
TAG
=
"OggVorbisExtractor"
;
private
static
final
int
OGG_MAX_SEGMENT_SIZE
=
255
;
private
final
ParsableByteArray
scratch
=
new
ParsableByteArray
(
new
byte
[
OGG_MAX_SEGMENT_SIZE
*
255
],
0
);
private
final
OggReader
oggReader
=
new
OggReader
();
private
TrackOutput
trackOutput
;
private
VorbisSetup
vorbisSetup
;
private
int
previousPacketBlockSize
;
private
long
elapsedSamples
;
private
boolean
seenFirstAudioPacket
;
private
VorbisUtil
.
VorbisIdHeader
vorbisIdHeader
;
private
VorbisUtil
.
CommentHeader
commentHeader
;
@Override
public
boolean
sniff
(
ExtractorInput
input
)
throws
IOException
,
InterruptedException
{
try
{
OggReader
.
PageHeader
header
=
new
OggReader
.
PageHeader
();
OggReader
.
populatePageHeader
(
input
,
header
,
scratch
,
true
);
if
((
header
.
type
&
0x02
)
!=
0x02
)
{
throw
new
ParserException
(
"expected page to be first page of a logical stream"
);
}
input
.
resetPeekPosition
();
}
catch
(
ParserException
e
)
{
Log
.
e
(
TAG
,
e
.
getMessage
());
return
false
;
}
return
true
;
}
@Override
public
void
init
(
ExtractorOutput
output
)
{
trackOutput
=
output
.
track
(
0
);
output
.
endTracks
();
output
.
seekMap
(
SeekMap
.
UNSEEKABLE
);
}
@Override
public
void
seek
()
{
oggReader
.
reset
();
previousPacketBlockSize
=
-
1
;
elapsedSamples
=
0
;
seenFirstAudioPacket
=
false
;
scratch
.
reset
();
}
@Override
public
int
read
(
ExtractorInput
input
,
PositionHolder
seekPosition
)
throws
IOException
,
InterruptedException
{
if
(
vorbisSetup
==
null
)
{
vorbisSetup
=
readSetupHeaders
(
input
,
scratch
);
ArrayList
<
byte
[]>
codecInitialisationData
=
new
ArrayList
<>();
codecInitialisationData
.
clear
();
codecInitialisationData
.
add
(
vorbisSetup
.
idHeader
.
data
);
codecInitialisationData
.
add
(
vorbisSetup
.
setupHeaderData
);
long
duration
=
input
.
getLength
()
==
C
.
LENGTH_UNBOUNDED
?
C
.
UNKNOWN_TIME_US
:
input
.
getLength
()
*
8000000
/
vorbisSetup
.
idHeader
.
getApproximateBitrate
();
trackOutput
.
format
(
MediaFormat
.
createAudioFormat
(
null
,
MimeTypes
.
AUDIO_VORBIS
,
this
.
vorbisSetup
.
idHeader
.
bitrateNominal
,
OGG_MAX_SEGMENT_SIZE
*
255
,
duration
,
this
.
vorbisSetup
.
idHeader
.
channels
,
(
int
)
this
.
vorbisSetup
.
idHeader
.
sampleRate
,
codecInitialisationData
,
null
));
}
if
(
oggReader
.
readPacket
(
input
,
scratch
))
{
// if this is an audio packet...
if
((
scratch
.
data
[
0
]
&
0x01
)
!=
1
)
{
// ... we need to decode the block size
int
packetBlockSize
=
decodeBlockSize
(
scratch
.
data
[
0
],
vorbisSetup
);
// a packet contains samples produced from overlapping the previous and current frame data
// (https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-350001.3.2)
int
samplesInPacket
=
seenFirstAudioPacket
?
(
packetBlockSize
+
previousPacketBlockSize
)
/
4
:
0
;
// codec expects the number of samples appended to audio data
appendNumberOfSamples
(
scratch
,
samplesInPacket
);
// calculate time and send audio data to codec
long
timeUs
=
elapsedSamples
*
C
.
MICROS_PER_SECOND
/
vorbisSetup
.
idHeader
.
sampleRate
;
trackOutput
.
sampleData
(
scratch
,
scratch
.
limit
());
trackOutput
.
sampleMetadata
(
timeUs
,
C
.
SAMPLE_FLAG_SYNC
,
scratch
.
limit
(),
0
,
null
);
// update state in members for next iteration
seenFirstAudioPacket
=
true
;
elapsedSamples
+=
samplesInPacket
;
previousPacketBlockSize
=
packetBlockSize
;
}
scratch
.
reset
();
return
RESULT_CONTINUE
;
}
return
RESULT_END_OF_INPUT
;
}
//@VisibleForTesting
/* package */
VorbisSetup
readSetupHeaders
(
ExtractorInput
input
,
ParsableByteArray
scratch
)
throws
IOException
,
InterruptedException
{
if
(
vorbisIdHeader
==
null
)
{
oggReader
.
readPacket
(
input
,
scratch
);
vorbisIdHeader
=
VorbisUtil
.
readVorbisIdentificationHeader
(
scratch
);
scratch
.
reset
();
}
if
(
commentHeader
==
null
)
{
oggReader
.
readPacket
(
input
,
scratch
);
commentHeader
=
VorbisUtil
.
readVorbisCommentHeader
(
scratch
);
scratch
.
reset
();
}
oggReader
.
readPacket
(
input
,
scratch
);
// the third packet contains the setup header
byte
[]
setupHeaderData
=
new
byte
[
scratch
.
limit
()];
// raw data of vorbis setup header has to be passed to decoder as CSD buffer #2
System
.
arraycopy
(
scratch
.
data
,
0
,
setupHeaderData
,
0
,
scratch
.
limit
());
// partially decode setup header to get the modes
Mode
[]
modes
=
VorbisUtil
.
readVorbisModes
(
scratch
,
vorbisIdHeader
.
channels
);
// we need the ilog of modes all the time when extracting, so we compute it once
int
iLogModes
=
VorbisUtil
.
iLog
(
modes
.
length
-
1
);
scratch
.
reset
();
return
new
VorbisSetup
(
vorbisIdHeader
,
commentHeader
,
setupHeaderData
,
modes
,
iLogModes
);
}
//@VisibleForTesting
/* package */
static
void
appendNumberOfSamples
(
ParsableByteArray
buffer
,
long
packetSampleCount
)
{
buffer
.
setLimit
(
buffer
.
limit
()
+
4
);
// The vorbis decoder expects the number of samples in the packet
// to be appended to the audio data as an int32
buffer
.
data
[
buffer
.
limit
()
-
4
]
=
(
byte
)
((
packetSampleCount
)
&
0xFF
);
buffer
.
data
[
buffer
.
limit
()
-
3
]
=
(
byte
)
((
packetSampleCount
>>>
8
)
&
0xFF
);
buffer
.
data
[
buffer
.
limit
()
-
2
]
=
(
byte
)
((
packetSampleCount
>>>
16
)
&
0xFF
);
buffer
.
data
[
buffer
.
limit
()
-
1
]
=
(
byte
)
((
packetSampleCount
>>>
24
)
&
0xFF
);
}
private
static
int
decodeBlockSize
(
byte
firstByteOfAudioPacket
,
VorbisSetup
vorbisSetup
)
{
// read modeNumber (https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-730004.3.1)
int
modeNumber
=
VorbisUtil
.
readBits
(
firstByteOfAudioPacket
,
vorbisSetup
.
iLogModes
,
1
);
int
currentBlockSize
;
if
(!
vorbisSetup
.
modes
[
modeNumber
].
blockFlag
)
{
currentBlockSize
=
vorbisSetup
.
idHeader
.
blockSize0
;
}
else
{
currentBlockSize
=
vorbisSetup
.
idHeader
.
blockSize1
;
}
return
currentBlockSize
;
}
/**
* Class to hold all data read from Vorbis setup headers.
*/
/* package */
static
final
class
VorbisSetup
{
public
final
VorbisUtil
.
VorbisIdHeader
idHeader
;
public
final
VorbisUtil
.
CommentHeader
commentHeader
;
public
final
byte
[]
setupHeaderData
;
public
final
Mode
[]
modes
;
public
final
int
iLogModes
;
public
VorbisSetup
(
VorbisUtil
.
VorbisIdHeader
idHeader
,
VorbisUtil
.
CommentHeader
commentHeader
,
byte
[]
setupHeaderData
,
Mode
[]
modes
,
int
iLogModes
)
{
this
.
idHeader
=
idHeader
;
this
.
commentHeader
=
commentHeader
;
this
.
setupHeaderData
=
setupHeaderData
;
this
.
modes
=
modes
;
this
.
iLogModes
=
iLogModes
;
}
}
}
library/src/main/java/com/google/android/exoplayer/extractor/ogg/VorbisBitArray.java
0 → 100644
View file @
89ce1cce
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer
.
extractor
.
ogg
;
import
com.google.android.exoplayer.util.Assertions
;
/**
* Wraps a byte array, providing methods that allow it to be read as a vorbis bitstream.
*
* @see <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-360002">Vorbis bitpacking
* specification</a>
*/
/* package */
final
class
VorbisBitArray
{
public
final
byte
[]
data
;
private
int
limit
;
private
int
byteOffset
;
private
int
bitOffset
;
/**
* Creates a new instance that wraps an existing array.
*
* @param data the array to wrap.
*/
public
VorbisBitArray
(
byte
[]
data
)
{
this
(
data
,
data
.
length
);
}
/**
* Creates a new instance that wraps an existing array.
*
* @param data the array to wrap.
* @param limit the limit in bytes.
*/
public
VorbisBitArray
(
byte
[]
data
,
int
limit
)
{
this
.
data
=
data
;
this
.
limit
=
limit
*
8
;
}
/** Resets the reading position to zero. */
public
void
reset
()
{
byteOffset
=
0
;
bitOffset
=
0
;
}
/**
* Reads a single bit.
*
* @return {@code true} if the bit is set, {@code false} otherwise.
*/
public
boolean
readBit
()
{
return
readBits
(
1
)
==
1
;
}
/**
* Reads up to 32 bits.
*
* @param numBits The number of bits to read.
* @return An int whose bottom {@code numBits} bits hold the read data.
*/
public
int
readBits
(
int
numBits
)
{
Assertions
.
checkState
(
getPosition
()
+
numBits
<=
limit
);
if
(
numBits
==
0
)
{
return
0
;
}
int
result
=
0
;
int
bitCount
=
0
;
if
(
bitOffset
!=
0
)
{
bitCount
=
Math
.
min
(
numBits
,
8
-
bitOffset
);
int
mask
=
0xFF
>>>
(
8
-
bitCount
);
result
=
(
data
[
byteOffset
]
>>>
bitOffset
)
&
mask
;
bitOffset
+=
bitCount
;
if
(
bitOffset
==
8
)
{
byteOffset
++;
bitOffset
=
0
;
}
}
if
(
numBits
-
bitCount
>
7
)
{
int
numBytes
=
(
numBits
-
bitCount
)
/
8
;
for
(
int
i
=
0
;
i
<
numBytes
;
i
++)
{
result
|=
(
data
[
byteOffset
++]
&
0xFF
L
)
<<
bitCount
;
bitCount
+=
8
;
}
}
if
(
numBits
>
bitCount
)
{
int
bitsOnNextByte
=
numBits
-
bitCount
;
int
mask
=
0xFF
>>>
(
8
-
bitsOnNextByte
);
result
|=
(
data
[
byteOffset
]
&
mask
)
<<
bitCount
;
bitOffset
+=
bitsOnNextByte
;
}
return
result
;
}
/**
* Skips {@code numberOfBits} bits.
*
* @param numberOfBits the number of bits to skip.
*/
public
void
skipBits
(
int
numberOfBits
)
{
Assertions
.
checkState
(
getPosition
()
+
numberOfBits
<=
limit
);
byteOffset
+=
numberOfBits
/
8
;
bitOffset
+=
numberOfBits
%
8
;
if
(
bitOffset
>
7
)
{
byteOffset
++;
bitOffset
-=
8
;
}
}
/**
* Gets the current reading position in bits.
*
* @return the current reading position in bits.
*/
public
int
getPosition
()
{
return
byteOffset
*
8
+
bitOffset
;
}
/**
* Sets the index of the current reading position in bits.
*
* @param position the new reading position in bits.
*/
public
void
setPosition
(
int
position
)
{
Assertions
.
checkArgument
(
position
<
limit
&&
position
>=
0
);
byteOffset
=
position
/
8
;
bitOffset
=
position
-
(
byteOffset
*
8
);
}
/**
* Gets the number of remaining bits.
*
* @return number of remaining bits.
*/
public
int
bitsLeft
()
{
return
limit
-
getPosition
();
}
/**
* Returns the limit in bits.
*
* @return the limit in bits.
**/
public
int
limit
()
{
return
limit
;
}
}
library/src/main/java/com/google/android/exoplayer/extractor/ogg/VorbisUtil.java
0 → 100644
View file @
89ce1cce
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer
.
extractor
.
ogg
;
import
com.google.android.exoplayer.ParserException
;
import
com.google.android.exoplayer.util.ParsableByteArray
;
import
android.util.Log
;
import
java.util.Arrays
;
/**
* Utility methods for parsing vorbis streams.
*/
/* package */
final
class
VorbisUtil
{
private
static
final
String
TAG
=
"VorbisUtil"
;
/**
* Returns ilog(x), which is the index of the highest set bit in {@code x}.
*
* @see <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-1190009.2.1">
* Vorbis spec</a>
* @param x the value of which the ilog should be calculated.
* @return ilog(x)
*/
public
static
int
iLog
(
int
x
)
{
int
val
=
0
;
while
(
x
>
0
)
{
val
++;
x
>>>=
1
;
}
return
val
;
}
/**
* Reads an int of {@code length} bits from {@code src} starting at
* {@code leastSignificantBitIndex}.
*
* @param src the {@code byte} to read from.
* @param length the length in bits of the int to read.
* @param leastSignificantBitIndex the index of the least significant bit of the int to read.
* @return the int value read.
*/
public
static
int
readBits
(
byte
src
,
int
length
,
int
leastSignificantBitIndex
)
{
return
(
src
>>
leastSignificantBitIndex
)
&
(
255
>>>
(
8
-
length
));
}
/**
* Reads a vorbis identification header from {@code headerData}.
*
* @see <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-630004.2.2">Vorbis
* spec/Identification header</a>
* @param headerData a {@link ParsableByteArray} wrapping the header data.
* @return a {@link VorbisUtil.VorbisIdHeader} with meta data.
* @throws ParserException thrown if invalid capture pattern is detected.
*/
public
static
VorbisIdHeader
readVorbisIdentificationHeader
(
ParsableByteArray
headerData
)
throws
ParserException
{
captureVorbisHeader
(
0x01
,
headerData
);
long
version
=
headerData
.
readLittleEndianUnsignedInt
();
int
channels
=
headerData
.
readUnsignedByte
();
long
sampleRate
=
headerData
.
readLittleEndianUnsignedInt
();
int
bitrateMax
=
headerData
.
readLittleEndianInt
();
int
bitrateNominal
=
headerData
.
readLittleEndianInt
();
int
bitrateMin
=
headerData
.
readLittleEndianInt
();
int
blockSize
=
headerData
.
readUnsignedByte
();
int
blockSize0
=
(
int
)
Math
.
pow
(
2
,
blockSize
&
0x0F
);
int
blockSize1
=
(
int
)
Math
.
pow
(
2
,
(
blockSize
&
0xF0
)
>>
4
);
boolean
framingFlag
=
(
headerData
.
readUnsignedByte
()
&
0x01
)
>
0
;
// raw data of vorbis setup header has to be passed to decoder as CSD buffer #1
byte
[]
data
=
Arrays
.
copyOf
(
headerData
.
data
,
headerData
.
limit
());
return
new
VorbisIdHeader
(
version
,
channels
,
sampleRate
,
bitrateMax
,
bitrateNominal
,
bitrateMin
,
blockSize0
,
blockSize1
,
framingFlag
,
data
);
}
/**
* Reads a vorbis comment header.
*
* @see <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-640004.2.3">
* Vorbis spec/Comment header</a>
* @param headerData a {@link ParsableByteArray} wrapping the header data.
* @return a {@link VorbisUtil.CommentHeader} with all the comments.
* @throws ParserException thrown if invalid capture pattern is detected.
*/
public
static
CommentHeader
readVorbisCommentHeader
(
ParsableByteArray
headerData
)
throws
ParserException
{
int
length
=
captureVorbisHeader
(
0x03
,
headerData
);
int
len
=
(
int
)
headerData
.
readLittleEndianUnsignedInt
();
length
+=
4
;
String
vendor
=
headerData
.
readString
(
len
);
length
+=
vendor
.
length
();
long
commentListLen
=
headerData
.
readLittleEndianUnsignedInt
();
String
[]
comments
=
new
String
[(
int
)
commentListLen
];
length
+=
4
;
for
(
int
i
=
0
;
i
<
commentListLen
;
i
++)
{
len
=
(
int
)
headerData
.
readLittleEndianUnsignedInt
();
length
+=
4
;
comments
[
i
]
=
headerData
.
readString
(
len
);
length
+=
comments
[
i
].
length
();
}
if
((
headerData
.
readUnsignedByte
()
&
0x01
)
==
0
)
{
throw
new
ParserException
(
"framing bit expected to be set"
);
}
length
+=
1
;
return
new
CommentHeader
(
vendor
,
comments
,
length
);
}
private
static
int
captureVorbisHeader
(
int
headerType
,
ParsableByteArray
idHeader
)
throws
ParserException
{
if
(
idHeader
.
readUnsignedByte
()
!=
headerType
)
{
throw
new
ParserException
(
"expected header type "
+
Integer
.
toHexString
(
headerType
));
}
if
(!(
idHeader
.
readUnsignedByte
()
==
'v'
&&
idHeader
.
readUnsignedByte
()
==
'o'
&&
idHeader
.
readUnsignedByte
()
==
'r'
&&
idHeader
.
readUnsignedByte
()
==
'b'
&&
idHeader
.
readUnsignedByte
()
==
'i'
&&
idHeader
.
readUnsignedByte
()
==
's'
))
{
throw
new
ParserException
(
"expected characters 'vorbis'"
);
}
return
7
;
// bytes read
}
/**
* This method reads the modes which are located at the very end of the vorbis setup header.
* That's why we need to partially decode or at least read the entire setup header to know
* where to start reading the modes.
*
* @see <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-650004.2.4">
* Vorbis spec/Setup header</a>
* @param headerData a {@link ParsableByteArray} containing setup header data.
* @param channels the number of channels.
* @return an array of {@link Mode}s.
* @throws ParserException thrown if bit stream is invalid.
*/
public
static
Mode
[]
readVorbisModes
(
ParsableByteArray
headerData
,
int
channels
)
throws
ParserException
{
captureVorbisHeader
(
0x05
,
headerData
);
int
numberOfBooks
=
headerData
.
readUnsignedByte
()
+
1
;
VorbisBitArray
bitArray
=
new
VorbisBitArray
(
headerData
.
data
);
bitArray
.
skipBits
(
headerData
.
getPosition
()
*
8
);
for
(
int
i
=
0
;
i
<
numberOfBooks
;
i
++)
{
readBook
(
bitArray
);
}
int
timeCount
=
bitArray
.
readBits
(
6
)
+
1
;
for
(
int
i
=
0
;
i
<
timeCount
;
i
++)
{
if
(
bitArray
.
readBits
(
16
)
!=
0x00
)
{
throw
new
ParserException
(
"placeholder of time domain transforms not zeroed out"
);
}
}
readFloors
(
bitArray
);
readResidues
(
bitArray
);
readMappings
(
channels
,
bitArray
);
Mode
[]
modes
=
readModes
(
bitArray
);
if
(!
bitArray
.
readBit
())
{
throw
new
ParserException
(
"framing bit after modes not set as expected"
);
}
return
modes
;
}
private
static
Mode
[]
readModes
(
VorbisBitArray
bitArray
)
throws
ParserException
{
int
modeCount
=
bitArray
.
readBits
(
6
)
+
1
;
Mode
[]
modes
=
new
Mode
[
modeCount
];
for
(
int
i
=
0
;
i
<
modeCount
;
i
++)
{
boolean
blockFlag
=
bitArray
.
readBit
();
int
windowType
=
bitArray
.
readBits
(
16
);
int
transformType
=
bitArray
.
readBits
(
16
);
int
mapping
=
bitArray
.
readBits
(
8
);
modes
[
i
]
=
new
Mode
(
blockFlag
,
windowType
,
transformType
,
mapping
);
}
return
modes
;
}
private
static
void
readMappings
(
int
channels
,
VorbisBitArray
bitArray
)
throws
ParserException
{
int
mappingsCount
=
bitArray
.
readBits
(
6
)
+
1
;
for
(
int
i
=
0
;
i
<
mappingsCount
;
i
++)
{
int
mappingType
=
bitArray
.
readBits
(
16
);
switch
(
mappingType
)
{
case
0
:
int
submaps
;
if
(
bitArray
.
readBit
())
{
submaps
=
bitArray
.
readBits
(
4
)
+
1
;
}
else
{
submaps
=
1
;
}
int
couplingSteps
;
if
(
bitArray
.
readBit
())
{
couplingSteps
=
bitArray
.
readBits
(
8
)
+
1
;
for
(
int
j
=
0
;
j
<
couplingSteps
;
j
++)
{
bitArray
.
skipBits
(
iLog
(
channels
-
1
));
// magnitude
bitArray
.
skipBits
(
iLog
(
channels
-
1
));
// angle
}
}
/*else {
couplingSteps = 0;
}*/
if
(
bitArray
.
readBits
(
2
)
!=
0x00
)
{
throw
new
ParserException
(
"to reserved bits must be zero after mapping coupling steps"
);
}
if
(
submaps
>
1
)
{
for
(
int
j
=
0
;
j
<
channels
;
j
++)
{
bitArray
.
skipBits
(
4
);
// mappingMux
}
}
for
(
int
j
=
0
;
j
<
submaps
;
j
++)
{
bitArray
.
skipBits
(
8
);
// discard
bitArray
.
skipBits
(
8
);
// submapFloor
bitArray
.
skipBits
(
8
);
// submapResidue
}
break
;
default
:
Log
.
e
(
TAG
,
"mapping type other than 0 not supported: "
+
mappingType
);
}
}
}
private
static
void
readResidues
(
VorbisBitArray
bitArray
)
throws
ParserException
{
int
residueCount
=
bitArray
.
readBits
(
6
)
+
1
;
for
(
int
i
=
0
;
i
<
residueCount
;
i
++)
{
int
residueType
=
bitArray
.
readBits
(
16
);
if
(
residueType
>
2
)
{
throw
new
ParserException
(
"residueType greater than 2 is not decodable"
);
}
else
{
bitArray
.
skipBits
(
24
);
// begin
bitArray
.
skipBits
(
24
);
// end
bitArray
.
skipBits
(
24
);
// partitionSize (add one)
int
classifications
=
bitArray
.
readBits
(
6
)
+
1
;
bitArray
.
skipBits
(
8
);
// classbook
int
[]
cascade
=
new
int
[
classifications
];
for
(
int
j
=
0
;
j
<
classifications
;
j
++)
{
int
highBits
=
0
;
int
lowBits
=
bitArray
.
readBits
(
3
);
if
(
bitArray
.
readBit
())
{
highBits
=
bitArray
.
readBits
(
5
);
}
cascade
[
j
]
=
highBits
*
8
+
lowBits
;
}
for
(
int
j
=
0
;
j
<
classifications
;
j
++)
{
for
(
int
k
=
0
;
k
<
8
;
k
++)
{
if
((
cascade
[
j
]
&
(
0x01
<<
k
))
!=
0
)
{
bitArray
.
skipBits
(
8
);
// discard
}
}
}
}
}
}
private
static
void
readFloors
(
VorbisBitArray
bitArray
)
throws
ParserException
{
int
floorCount
=
bitArray
.
readBits
(
6
)
+
1
;
for
(
int
i
=
0
;
i
<
floorCount
;
i
++)
{
int
floorType
=
bitArray
.
readBits
(
16
);
switch
(
floorType
)
{
case
0
:
bitArray
.
skipBits
(
8
);
//order
bitArray
.
skipBits
(
16
);
// rate
bitArray
.
skipBits
(
16
);
// barkMapSize
bitArray
.
skipBits
(
6
);
// amplitudeBits
bitArray
.
skipBits
(
8
);
// amplitudeOffset
int
floorNumberOfBooks
=
bitArray
.
readBits
(
4
)
+
1
;
for
(
int
j
=
0
;
j
<
floorNumberOfBooks
;
j
++)
{
bitArray
.
skipBits
(
8
);
}
break
;
case
1
:
int
partitions
=
bitArray
.
readBits
(
5
);
int
maximumClass
=
-
1
;
int
[]
partitionClassList
=
new
int
[
partitions
];
for
(
int
j
=
0
;
j
<
partitions
;
j
++)
{
partitionClassList
[
j
]
=
bitArray
.
readBits
(
4
);
if
(
partitionClassList
[
j
]
>
maximumClass
)
{
maximumClass
=
partitionClassList
[
j
];
}
}
int
[]
classDimensions
=
new
int
[
maximumClass
+
1
];
for
(
int
j
=
0
;
j
<
classDimensions
.
length
;
j
++)
{
classDimensions
[
j
]
=
bitArray
.
readBits
(
3
)
+
1
;
int
classSubclasses
=
bitArray
.
readBits
(
2
);
if
(
classSubclasses
>
0
)
{
bitArray
.
skipBits
(
8
);
// classMasterbooks
}
for
(
int
k
=
0
;
k
<
(
1
<<
classSubclasses
);
k
++)
{
bitArray
.
skipBits
(
8
);
// subclassBook (subtract 1)
}
}
bitArray
.
skipBits
(
2
);
// multiplier (add one)
int
rangeBits
=
bitArray
.
readBits
(
4
);
int
count
=
0
;
for
(
int
j
=
0
,
k
=
0
;
j
<
partitions
;
j
++)
{
int
idx
=
partitionClassList
[
j
];
count
+=
classDimensions
[
idx
];
for
(;
k
<
count
;
k
++)
{
bitArray
.
skipBits
(
rangeBits
);
// floorValue
}
}
break
;
default
:
throw
new
ParserException
(
"floor type greater than 1 not decodable: "
+
floorType
);
}
}
}
private
static
CodeBook
readBook
(
VorbisBitArray
bitArray
)
throws
ParserException
{
if
(
bitArray
.
readBits
(
24
)
!=
0x564342
)
{
throw
new
ParserException
(
"expected code book to start with [0x56, 0x43, 0x42] at "
+
bitArray
.
getPosition
());
}
int
dimensions
=
bitArray
.
readBits
(
16
);
int
entries
=
bitArray
.
readBits
(
24
);
long
[]
lengthMap
=
new
long
[
entries
];
boolean
isOrdered
=
bitArray
.
readBit
();
if
(!
isOrdered
)
{
boolean
isSparse
=
bitArray
.
readBit
();
for
(
int
i
=
0
;
i
<
lengthMap
.
length
;
i
++)
{
if
(
isSparse
)
{
if
(
bitArray
.
readBit
())
{
lengthMap
[
i
]
=
bitArray
.
readBits
(
5
)
+
1
;
}
else
{
// entry unused
lengthMap
[
i
]
=
0
;
}
}
else
{
// not sparse
lengthMap
[
i
]
=
bitArray
.
readBits
(
5
)
+
1
;
}
}
}
else
{
int
length
=
bitArray
.
readBits
(
5
)
+
1
;
for
(
int
i
=
0
;
i
<
lengthMap
.
length
;)
{
int
num
=
bitArray
.
readBits
(
iLog
(
entries
-
i
));
for
(
int
j
=
0
;
j
<
num
&&
i
<
lengthMap
.
length
;
i
++,
j
++)
{
lengthMap
[
i
]
=
length
;
}
length
++;
}
}
int
lookupType
=
bitArray
.
readBits
(
4
);
if
(
lookupType
>
2
)
{
throw
new
ParserException
(
"lookup type greater than 2 not decodable: "
+
lookupType
);
}
else
if
(
lookupType
==
1
||
lookupType
==
2
)
{
bitArray
.
skipBits
(
32
);
// minimumValue
bitArray
.
skipBits
(
32
);
// deltaValue
int
valueBits
=
bitArray
.
readBits
(
4
)
+
1
;
bitArray
.
skipBits
(
1
);
// sequenceP
long
lookupValuesCount
;
if
(
lookupType
==
1
)
{
if
(
dimensions
!=
0
)
{
lookupValuesCount
=
mapType1QuantValues
(
entries
,
dimensions
);
}
else
{
// TODO no sample file found yet
lookupValuesCount
=
0
;
}
}
else
{
// TODO no sample file found yet
lookupValuesCount
=
entries
*
dimensions
;
}
// discard (no decoding required yet)
bitArray
.
skipBits
((
int
)
(
lookupValuesCount
*
valueBits
));
}
return
new
CodeBook
(
dimensions
,
entries
,
lengthMap
,
lookupType
,
isOrdered
);
}
/**
* @see <a href="http://svn.xiph.org/trunk/vorbis/lib/sharedbook.c">function
* _book_maptype1_quantvals</a> of libvorbis.
*/
private
static
long
mapType1QuantValues
(
long
entries
,
long
dimension
)
{
return
(
long
)
Math
.
floor
(
Math
.
pow
((
double
)
entries
,
1
.
d
/
dimension
));
}
public
static
final
class
CodeBook
{
public
final
int
dimensions
;
public
final
int
entries
;
public
final
long
[]
lengthMap
;
public
final
int
lookupType
;
public
final
boolean
isOrdered
;
public
CodeBook
(
int
dimensions
,
int
entries
,
long
[]
lengthMap
,
int
lookupType
,
boolean
isOrdered
)
{
this
.
dimensions
=
dimensions
;
this
.
entries
=
entries
;
this
.
lengthMap
=
lengthMap
;
this
.
lookupType
=
lookupType
;
this
.
isOrdered
=
isOrdered
;
}
}
public
static
final
class
CommentHeader
{
public
final
String
vendor
;
public
final
String
[]
comments
;
public
final
int
length
;
public
CommentHeader
(
String
vendor
,
String
[]
comments
,
int
length
)
{
this
.
vendor
=
vendor
;
this
.
comments
=
comments
;
this
.
length
=
length
;
}
}
public
static
final
class
VorbisIdHeader
{
public
final
long
version
;
public
final
int
channels
;
public
final
long
sampleRate
;
public
final
int
bitrateMax
;
public
final
int
bitrateNominal
;
public
final
int
bitrateMin
;
public
final
int
blockSize0
;
public
final
int
blockSize1
;
public
final
boolean
framingFlag
;
public
final
byte
[]
data
;
public
VorbisIdHeader
(
long
version
,
int
channels
,
long
sampleRate
,
int
bitrateMax
,
int
bitrateNominal
,
int
bitrateMin
,
int
blockSize0
,
int
blockSize1
,
boolean
framingFlag
,
byte
[]
data
)
{
this
.
version
=
version
;
this
.
channels
=
channels
;
this
.
sampleRate
=
sampleRate
;
this
.
bitrateMax
=
bitrateMax
;
this
.
bitrateNominal
=
bitrateNominal
;
this
.
bitrateMin
=
bitrateMin
;
this
.
blockSize0
=
blockSize0
;
this
.
blockSize1
=
blockSize1
;
this
.
framingFlag
=
framingFlag
;
this
.
data
=
data
;
}
public
int
getApproximateBitrate
()
{
return
bitrateNominal
==
0
?
(
bitrateMin
+
bitrateMax
)
/
2
:
bitrateNominal
;
}
}
public
static
final
class
Mode
{
public
final
boolean
blockFlag
;
public
final
int
windowType
;
public
final
int
transformType
;
public
final
int
mapping
;
public
Mode
(
boolean
blockFlag
,
int
windowType
,
int
transformType
,
int
mapping
)
{
this
.
blockFlag
=
blockFlag
;
this
.
windowType
=
windowType
;
this
.
transformType
=
transformType
;
this
.
mapping
=
mapping
;
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment