[xiph-cvs] cvs commit: theora/doc spec.txt testspec2.ogg testspec2.raw txt2html.py txt2py.py spec.html spec.py testspec.ogg
Ralph Giles
giles at xiph.org
Tue Jul 15 04:29:10 PDT 2003
giles 03/07/15 07:29:10
Modified: doc spec.html spec.py testspec.ogg
Added: doc spec.txt testspec2.ogg testspec2.raw txt2html.py
txt2py.py
Log:
Updated Theora specification documents and examples from Dan Miller.
Revision Changes Path
1.2 +392 -203 theora/doc/spec.html
Index: spec.html
===================================================================
RCS file: /usr/local/cvsroot/theora/doc/spec.html,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- spec.html 5 Jul 2003 23:18:14 -0000 1.1
+++ spec.html 15 Jul 2003 11:29:09 -0000 1.2
@@ -1,32 +1,58 @@
-<html><body></pre><font face="Times New Roman"><h2><u>Theora Bitstream Specification and Reference Decoder -- Theora 1.0
-</h2></u><br><font face="Courier New"><pre>
+<html><body></pre><font face="Times New Roman">spec060 -- new stuff
+<br>spec061 -- finally -- bitwise equivalent to C code! (without loop filter)
+<br>spec062 -- FINALLY -- bitwise equvalent, even for TKAL! problem was dang page/packet stuff
+<br> this works sorta, but still needs to be revamped so Ogg stuff is not brittle
+<br> but at least it works with its own test data. Now gotta add loop filter
+<br>spec063 -- some tweaks
+<br>spec064 -- loop filter -- not working yet, but reorged pixel maps & stuff
+<br>spec065 -- loop filter working! (?) yes!
+<br>spec066 -- cleanup time -- derf's comments, other stuff (see unk.txt)
+<br> firster -- fix up UV ala C code
+<br>spec067 -- first -- fixing header parsing stuff
+<br>spec068 -- decode_packet() -- now we can do a proper main loop
+<br>spec069 -- ok, using correct logic for headers & frames
+<br>spec070 -- cleaned up for release as 0.070
+<br>spec071 -- take command line args, insist on info & table headers -- make it 0.071
+<br><font face="Courier New"><pre>
+</pre><font face="Times New Roman"><h2><u>Theora Bitstream Specification and Reference Decoder -- Theora 1.0
+</h2></u><br><b>Document version: 0.071
+</b><br><font face="Courier New"><pre>
</pre><font face="Times New Roman"><i>(c) 2003 Xiph Foundation, Dan Miller
</i><br><font face="Courier New"><pre>
-</pre><font face="Times New Roman"><i>special thanks to various people at On2 Technologies for donating VP3, and to the folks at Xiph.org Foundation for doing good things with it
-</i><br><font face="Courier New"><pre>
-</pre><font face="Times New Roman"><i>This documentation is released under the yada yada open free gnu/BDS license etc.
+</pre><font face="Times New Roman"><i>special thanks to various people at On2 Technologies for donating VP3, and to the folks at Xiph.org Foundation for doing good things with it. Particular shout outs to Mike Melansen, Tim Teriberry, Ralph Giles, Christopher Montgomery, Mauricio Piacentini, and Jack Moffit (please let me know if I spelled your name wrong..)
</i><br><font face="Courier New"><pre>
-</pre><font face="Times New Roman"><i>Theora is a video codec. This is the spec.
+</pre><font face="Times New Roman"><i>This documentation and software are distributed under the terms of the BSD-style Theora license, as outlined in the "COPYING" file in the root directory of this distribution. Please familiarize yourself with these terms before distributing any of the documents in this directory.
</i><br><font face="Courier New"><pre>
-
</pre><font face="Times New Roman"><h3><u>Introduction
-</h3></u><br><b><u>About this document
+</h3></u><br><font face="Courier New"><pre>
+</pre><font face="Times New Roman">Theora is a video codec. This is the spec.
+<br><font face="Courier New"><pre>
+</pre><font face="Times New Roman"><b><u>State of this document
+</b></u><br><font face="Courier New"><pre>
+</pre><font face="Times New Roman">This document is unfinished. It is a work in progress that is included in the Theora release for your edification. Once it is complete and verified, it will hopefully become the canonical reference for Theora compatibility.
+<br><font face="Courier New"><pre>
+</pre><font face="Times New Roman">The most glaring deficiency is that presently the documentation and Python decoder only cover keyframes. We are actively looking for volunteers to help us complete the work of fully documenting the Theora format. If you are interested and believe you can help, please post a message to theora-dev at xiph.org, or contact jack at xiph.org or danbmil99 at yahoo.com.
+<br><font face="Courier New"><pre>
+</pre><font face="Times New Roman">In addition to support for predicted frames, the Python script needs to be heavily error-protected. Presently various illegal bitstreams will cause the program to go into an endless loop or crash in other unpredictable ways. The specification should eventually be usable as a syntax checker that is able to detect and report on any possible error condition within the bitstream. In addition to work on the code, we will need to generate a comprehensive test suite of encoded files that exercise every aspect of the bitstream. Illegal files will also need to be generated to test the error handling capacity of the script.
+<br><b><u>About this document
</b></u><br><font face="Courier New"><pre>
-</pre><font face="Times New Roman">This document is The Theora Bitstream Specification and Reference Decoder. It is both an english language description of the Theora video bitstream, and an interpretable program in the Python programming language, which can be executed using a version 2.0 or later Python interpreter. More information about Python can be gleaned at www.python.org. When run as a Python script, this document will decode compliant Theora bitstreams, producing uncompressed YUV files.
+</pre><font face="Times New Roman">This document is The Theora Bitstream Specification and Reference Decoder. It is both an english language description of the Theora video bitstream, and an interpretable program in the Python programming language, which can be executed using a version 2.0 or later Python interpreter. More information about Python can be gleaned at www.python.org. When run as a Python script, this document will decode compliant Theora bitstreams, producing uncompressed YUV files. The YUV output format is identical to that used by theora/win32/experimental/dumpvid/dump_vid.exe, which is as follows:
+<br><font face="Courier New"><pre>
+</pre><font face="Times New Roman">For each frame, Y pixel data is output as unsigned characters, scanning left to right for each row of pixels starting with the top row. The Y data is followed by interleaved V and U data, ie one scanline of V followed by one scanline of U. This format allows raw data to be inspected visually as a monochrome image, with the V and U planes situated directly below the Y plane.
<br><font face="Courier New"><pre>
</pre><font face="Times New Roman">To invoke this document as a Python program: at the command prompt, type:
-<br><font face="Courier New"><pre>[prompt]> python spec.py testspec.ogg
-
-</pre><font face="Times New Roman">The raw file will be saved as "out.raw"
+<br><font face="Courier New"><pre>[prompt]> python spec.py testspec.ogg out.raw
+</pre><font face="Times New Roman">The program will attempt to open and decode 'testspec.ogg'. The raw decoded file will be saved as "out.raw"
<br><font face="Courier New"><pre>
</pre><font face="Times New Roman"><b><u>Formatting Conventions
</b></u><br><font face="Courier New"><pre>
-</pre><font face="Times New Roman">There are two versions of this document: HTML, and Python. Both are created from the same source file.
+</pre><font face="Times New Roman">There are three versions of this document: text, HTML, and Python. The HTML and Python versions are created from the text file, spec.txt. While spec.txt is actually a legal Python script, the formatted version spec.py is more readable as the comments have been reformatted with linefeeds and formatting characters have been stripped. To create the HTML version spec.html, a simple hinting scheme is used to specify some rudimentary formatting (see txt2html.py for details). The following commands will regenerate both files from the source file:
<br><font face="Courier New"><pre>
+[prompt]> python txt2py.py spec.txt spec.py
+[prompt]> python txt2html.py spec.txt spec.html
+
</pre><font face="Times New Roman">In the HTML version, non-code sections are generally formatted using a variable-width font to distinguish them from code. Code and non-code can be interspersed, even within Python routines. In general, non-code blocks of text within routines will be italicized.
<br><font face="Courier New"><pre>
-</pre><font face="Times New Roman">The Python version is a simple ascii text file intended for viewing in a source code editor with a fixed-width font. Non-code sections are formatted as legal Python comments.
-<br><font face="Courier New"><pre>
</pre><font face="Times New Roman"><b><u>Overview
</b></u><br><font face="Courier New"><pre>
</pre><font face="Times New Roman">This document represents part of the overall specification package. The specification package includes the following elements:
@@ -37,9 +63,11 @@
* Verification Output Streams (uncompressed YUV data)
+</pre><font face="Times New Roman"><b><i>(Note: the following paragraph will not be considered in effect until this document is completed and verified - Ed.)
+</b></i><br><font face="Courier New"><pre>
</pre><font face="Times New Roman">A decoding application is Theora compliant IFF it can decode any Theora bitstream that is decodable with the Reference Decoder (this document), producing output that is bytewise equivalent. Several Verification Bitstreams and Verification Output Streams are included in the Specification Package for reference; the Verification Output Streams were produced using this document as a Python script. However, it is understood that a compliant decoder must be capable of decoding any legal Theora bitstream, not just those included in the Specification Package. A legal Theora bitstream is any bitstream that can be decoded by this document.
<br><font face="Courier New"><pre>
-</pre><font face="Times New Roman">Please note: the Python code herein is written solely to facilitate the definition and compliance testing of Theora bitstreams. It is by design an extremely inefficient and poorly structured piece of code. Do not use this as a template for real-world player applications. Instead, start with the C-based Theora decoder from CVS.
+</pre><font face="Times New Roman">Please note: the Python code herein is written solely to facilitate the definition and compliance testing of Theora bitstreams. It is by design an extremely inefficient and poorly structured piece of code. Do not use this as a template for real-world player applications. Instead, start with the C-based Theora decoder available for download at www.theora.org.
<br><font face="Courier New"><pre>
</pre><font face="Times New Roman">The Theora Bitstream Specification does not cover encoders, except for the following sentence:
<br><font face="Courier New"><pre>
@@ -55,27 +83,74 @@
<br><font face="Courier New"><pre>
from array import array
from os import abort
+import sys
-</pre><font face="Times New Roman">some globals & useful functions:
-<br><font face="Courier New"><pre>
-oggfile = file("testspec.ogg","rb")
+</pre><font face="Times New Roman"><i>usage:
+</i><br><font face="Courier New"><pre>
+if len(sys.argv) < 3:
+ print "usage: python spec.py infile outfile"
+ abort()
+
+</pre><font face="Times New Roman"><i>some globals & useful definitions:
+</i><br><font face="Courier New"><pre>
+</pre><font face="Times New Roman">oggfile = file("testspec.ogg","rb")
+<br><font face="Courier New"><pre>oggfile = file(sys.argv[1],"rb")
oggstring = oggfile.read() #NOTE limited by memory constraints -- should use file I/O
oggindex = 0
+pagebytes = 0
+pagestart =0
oggbyte = 0
bitmask = 0
oggbuf = array('B',oggstring) #convert to an array of unsigned bytes
huffs = [] #this will contain list of huffman trees
+infoflag = 0 #initialization flags
+tableflag = 0
</pre><font face="Times New Roman"><b><u>Bitstream parsing routines
</b></u><br><font face="Courier New"><pre>
-</pre><font face="Times New Roman">bit & byte ordering: For historical reasons, Ogg is generally little-endian, while Theora is big-endian when reading values larger than 8 bits directly from the stream. For byte reads (on byte boundaries), it doesn't matter; both schemes use the same bitpacking within a byte. These routines are intended primarily for reading the actual Theora bitstream. However for testing purposes, we have to implement a bit of Ogg since the test files are Ogg formatted. Note readlong() which is implemented to facilitate little-endian longword reads in the Ogg-aware routines.
+</pre><font face="Times New Roman">Bit & byte ordering: typically, Ogg packs bits starting with the most significant bit to the least. For historical reasons, Theora packs bits least significant bit first. In cases where values are byte-aligned (8 bit boundaries), this only affects byte ordering. We do some Ogg parsing but it happens to be only on byte-aligned values, so we use readbits(8) but reverse the byte order (See for instance readOgg32())
+<br><font face="Courier New"><pre>
+</pre><font face="Times New Roman">Note that in this specification we are assuming bytes are always 8 bit values. Future versions may support non-8-bit platforms.
<br><font face="Courier New"><pre>
+</pre><font face="Times New Roman"><i>helpers:
+</i><br><font face="Courier New"><pre>
+def flushpacket(): #flush bits between packets
+ global bitmask
+ bitmask = 0
+
+def flushpage(): #flush packet & disable paging for read_page_header()
+ global bitmask, pagebytes
+ bitmask = 0
+ pagebytes = 999999 #kluge - yuk
+
+</pre><font face="Times New Roman"><i>simple Ogg page header parsing routine. Note we are not checking CRC's; we are assuming Ogg data is not corrupt.
+</i><br><font face="Courier New"><pre>
+def read_page_header():
+ global oggindex, pagebytes, pagestart
+ flushpage()
+ oggs = readstring(4) #get the putated 4-byte Ogg identifier
+ if oggs != "OggS":
+ print "invalid page data -- OggS =", oggs
+ abort()
+ oggindex += 10 #serialnum at offset 14
+ serialno = readOgg32()
+ oggindex += 8 #segment count at offset 26
+ segments = readbits(8)
+ bytes = 0
+ for i in range(segments):
+ bytes += readbits(8)
+ pagebytes = bytes
+ pagestart = oggindex
+
+
</pre><font face="Times New Roman"><i>this routine just grabs a byte from the input stream:
</i><br><font face="Courier New"><pre>
def readbyte(): #note: this is a low-level function to read
#a byte-aligned octet from the datastream.
#To read an arbitrarily aligned byte, use readbits(8)
- global oggindex
+ global oggindex,pagebytes
+ if oggindex >= pagestart+pagebytes:
+ read_page_header()
byte = oggbuf[oggindex]
oggindex += 1
return byte
@@ -85,8 +160,8 @@
def readbit():
global bitmask, oggbyte
if bitmask == 0:
- bitmask = 0x80
oggbyte = readbyte()
+ bitmask = 0x80
if oggbyte & bitmask:
bit = 1
else:
@@ -94,12 +169,8 @@
bitmask >>= 1
return bit
-def flushpage(): #Ogg pages are byte-aligned; need to flush after using
- global bitmask
- bitmask = 0
-
</pre><font face="Times New Roman"><i>readbits: our workhorse. Gets up to 32 bits from the stream
-</i><br><i>(note -- hi bit is first bit read! use readlong() or build up values through sequential byte reads for Ogg purposes)
+</i><br><i>(note -- hi bit is first bit read! use readOgg32() or build up values through sequential byte reads for Ogg purposes)
</i><br><font face="Courier New"><pre>
def readbits(x):
ret = 0
@@ -116,9 +187,9 @@
s += chr(readbits(8))
return s
-</pre><font face="Times New Roman"><i>readlong reads a longword Ogg style:
+</pre><font face="Times New Roman"><i>readOgg32 reads a longword Ogg style:
</i><br><font face="Courier New"><pre>
-def readlong(): #different than readbits(32): byte order is reversed
+def readOgg32(): #different than readbits(32): byte order is reversed
return readbits(8) + (readbits(8) << 8) + (readbits(8) << 16) + (readbits(8) << 24)
@@ -132,9 +203,16 @@
<br><font face="Courier New"><pre>
</pre><font face="Times New Roman"><i>Note how this function is called recursively for each possible branch in the tree until all branches have bottomed out with complete bitstrings:
</i><br><font face="Courier New"><pre>
+hufftokens=0 #keep track of # of token strings -- 32 max
+
def read_hufftable(table):
+ global hufftokens
if readbit(): #if bit==1, this bitstring is complete
table.append( readbits(5) ) #next 5 bits = token number for this string
+ hufftokens += 1
+ if hufftokens > 32:
+ print "illegal huffman table, > 32 tokens"
+ abort()
else: #if bit was zero, we have two more entries defining
#the zero and one case for the next bit:
table.append([]) #add another pair of tables
@@ -159,11 +237,11 @@
</b><br><font face="Courier New"><pre>
</pre><font face="Times New Roman"><i>Each table contains the following five entries in this order:
</i><br><font face="Courier New"><pre>
- base run length
- number of extra run length bits (0 - 12)
- base value
- number of extra value bits (0 - 9)
- number of extra sign bits (0 or 1)
+# base run length
+# number of extra run length bits (0 - 12)
+# base value
+# number of extra value bits (0 - 9)
+# number of extra sign bits (0 or 1)
token_array = [
[1, 0, 'eob', 0, 0],
@@ -208,8 +286,8 @@
</i><br><font face="Courier New"><pre>
def parsetoken(huf):
global token_array #(not strictly necessary for read-only in Python)
-
token = readtoken(huf) #read a token from the stream
+
table = token_array[token] #get our table of parameters for this token
run = table[0] #base run length
run_extra = table[1] #number of extra bits for run length
@@ -233,50 +311,22 @@
#note: string * 1 = string, so 'eob', 'zrl' are OK
-</pre><font face="Times New Roman"><b><u>routines to read & parse headers
+</pre><font face="Times New Roman"><b><u>routines to read & parse codec headers
</b></u><br><font face="Courier New"><pre>
-</pre><font face="Times New Roman"><i>simple Ogg page header parsing routine:
-</i><br><font face="Courier New"><pre>
-def read_page_header():
- global oggindex
- flushpage()
- oggs = readstring(4) #get the putated 4-byte Ogg identifier
- if oggs != "OggS":
- print "invalid page data"
- abort()
- oggindex += 10 #serialnum at offset 14
- serialno = readlong()
- oggindex += 8 #segment count at offset 26
- segments = readbits(8)
- bytes = 0
- for i in range(segments):
- bytes += readbits(8)
-
</pre><font face="Times New Roman"><i>routine to parse the Theora info header:
-</i><br><i>[note: next three routines need to be rewritten so headers can come in any order]
</i><br><font face="Courier New"><pre>
def read_info_header():
global huffs, encoded_width, encoded_height, decode_width, decode_height, offset_x, offset_y
global fps_numerator, fps_denominator, aspect_numerator, aspect_denominator, quality, bitrate
- global version_major, version_minor, version_subminor, colorspace
-
- typeflag = readbits(8)
-
- if typeflag != 0x80: #first bit = 1; next 7 bits define header type.
- #for info header, 7 bit value = zero, so we have 0x80
- print "expected info header?"
- abort()
-
- cid = readstring(6) #codec ID
- if cid != "theora":
- print "Not a Theora header packet"
- abort()
+ global version_major, version_minor, version_subminor, colorspace, infoflag
version_major = readbits(8) #major & minor version must be exact match
if version_major != 3:
+ print "incompatible major version#"
abort()
version_minor = readbits(8)
if version_minor != 2:
+ print "incompatible minor version#"
abort()
version_subminor = readbits(8)
@@ -296,44 +346,24 @@
colorspace = readbits(8) #colorspace flag defines YUV to RGB mapping
bitrate = readbits(24) #target bitrate; not used for decode
quality = readbits(6) #target quality also not used for decode
-
+ infoflag = 1
</pre><font face="Times New Roman"><i>parse the comment header:
</i><br><font face="Courier New"><pre>
def read_comment_header():
global vendor_string, vendor_string_len, comment_string, comment_string_len
- typeflag = readbits(8)
-
- if typeflag != 0x81: #header type 1 = comment
- print "expected comment header? typeflag =",typeflag
- abort()
- cid = readstring(6)
- if cid != "theora":
- print "corrupted comment header?", cid
- abort()
-
- vendor_string_len = readlong()
+ vendor_string_len = readOgg32()
vendor_string = readstring(vendor_string_len)
- comment_string_len = readlong()
+ comment_string_len = readOgg32()
comment_string = readstring(comment_string_len)
</pre><font face="Times New Roman"><i>read & parse the table header:
</i><br><font face="Courier New"><pre>
def read_table_header():
- global scale_table_AC, scale_table_DC, Y_quantizer, UV_quantizer, IF_quantizer, frequency_counts
-
- typeflag = readbits(8)
-
- if typeflag != 0x82: #type 2 = table header
- print "expected table header? type = ", hex(typeflag)
- abort()
-
- cid = readstring(6)
- if cid != "theora":
- print "corrupted table header?", cid
- abort()
+ global scale_table_AC, scale_table_DC, Y_quantizer, UV_quantizer, IF_quantizer
+ global frequency_counts, hufftokens, tableflag
scale_table_AC = [] #64 possible quantizer scalers for AC coeffs
for x in range(64): scale_table_AC.append(readbits(16))
@@ -353,8 +383,38 @@
for x in range(80): #Read in huffman tables
huffs.append([])
+ hufftokens=0
read_hufftable(huffs[x])
+ tableflag = 1
+
+def decode_header():
+
+ header_type = readbits(7)
+
+ cid = readstring(6)
+ if cid != "theora":
+ print "not a theora stream header", cid
+ abort()
+
+ if header_type == 0:
+ read_info_header()
+ flushpacket()
+ return "info"
+
+ elif header_type == 1:
+ read_comment_header()
+ flushpacket()
+ return "comment"
+
+ elif header_type == 2:
+ read_table_header()
+ flushpacket()
+ return "table"
+
+ else:
+ print "unknown stream header type -- skipping"
+ return "unknown"
</pre><font face="Times New Roman"><b><u> Routines that decode video
</b></u><br><font face="Courier New"><pre>
@@ -414,7 +474,7 @@
p, q = hilbert[i] #nice Python syntax
xx = x*4 + p
yy = y*4 + q
- if (xx < w) & (yy < h): #skip stuff out of range
+ if (xx < w) & (yy < h): #skip stuff out of range
comap[xx][yy] = colist[ii] #if in range, get a coeff
ii += 1
return comap
@@ -444,7 +504,7 @@
if x == 0: #left column?
u = comap[0][y-1][0] #u = upper
ur = comap[1][y-1][0] #ur = upper-right
- p = u #[Shouldn't this be u*75 + ur*53??? but this works!]
+ p = u
comap[0][y][0] += p #add predictor to decoded value
else: #general case -- neither left column nor top row
@@ -484,7 +544,7 @@
where sf = scale_table_DC[quality_index] for DC dequantizer
scale_table_AC[quality_index] for AC dequantizer
-</pre><font face="Times New Roman"><i>Note that the dequantize routine also multiplies each coefficient by 4. This is to facilitate the iDCT later on.
+</pre><font face="Times New Roman"><i>(Note that the dequantize routine also multiplies each coefficient by 4. This is to facilitate the iDCT later on.)
</i><br><font face="Courier New"><pre>
def dequant(data, scaleDC, scaleAC, dqtable):
mul = int( (scaleDC * dqtable[0]) / 100 ) * 4
@@ -495,8 +555,10 @@
</pre><font face="Times New Roman"><b>ZIG-ZAG order
</b><br><font face="Courier New"><pre>
-</pre><font face="Times New Roman">The coefficients in each 8x8 DCT coded block are layed out in 'zig-zag' order. The following table shows the order in which the 64 coefficients are coded:
+</pre><font face="Times New Roman">The coefficients in each 8x8 DCT coded block are layed out in 'zig-zag' order.
<br><font face="Courier New"><pre>
+</pre><font face="Times New Roman"><i>The following table shows the order in which the 64 coefficients are coded:
+</i><br><font face="Courier New"><pre>
zigzag=[
0, 1, 5, 6, 14, 15, 27, 28,
2, 4, 7, 13, 16, 26, 29, 42,
@@ -524,46 +586,43 @@
</pre><font face="Times New Roman">addition and subtraction can be performed normally.
<br><font face="Courier New"><pre>
-</pre><font face="Times New Roman"><i>First we define a one-dimensional iDCT:
+</pre><font face="Times New Roman"><i>First we define a one-dimensional iDCT. Note that there are many implementations of iDCT available. Theora compatibility requires that the output of your iDCT routine be bitwise equivalent to the one outlined here:
</i><br><font face="Courier New"><pre>
def idct_1D(data, i, stride):
-</pre><font face="Times New Roman"><i>[where did these varnames come from? somebody make them instructive please]
-</i><br><font face="Courier New"><pre>
A = Mul_fix(64277, data[i+stride]) + Mul_fix(12785, data[i+7*stride])
B = Mul_fix(12785, data[i+stride]) - Mul_fix(64277, data[i+7*stride])
C = Mul_fix(54491, data[i+3*stride]) + Mul_fix(36410, data[i+5*stride])
D = Mul_fix(54491, data[i+5*stride]) - Mul_fix(36410, data[i+3*stride])
- Ad = Mul_fix(46341, A - C)
- Bd = Mul_fix(46341, B - D)
- Cd = A + C
- Dd = B + D
+ A2 = Mul_fix(46341, A - C)
+ B2 = Mul_fix(46341, B - D)
+ C2 = A + C
+ D2 = B + D
E = Mul_fix(46341, data[i] + data[i+4*stride])
F = Mul_fix(46341, data[i] - data[i+4*stride])
G = Mul_fix(60547, data[i+2*stride]) + Mul_fix(25080, data[i+6*stride])
H = Mul_fix(25080, data[i+2*stride]) - Mul_fix(60547, data[i+6*stride])
- Ed = E - G
- Gd = E + G
- Add = F + Ad
- Bdd = Bd - H
- Fd = F - Ad
- Hd = Bd + H
-
- data[i] = Gd + Cd
- data[i+stride] = Add + Hd
- data[i+2*stride] = Add - Hd
- data[i+3*stride] = Ed + Dd
- data[i+4*stride] = Ed - Dd
- data[i+5*stride] = Fd + Bdd
- data[i+6*stride] = Fd - Bdd
- data[i+7*stride] = Gd - Cd
+ E2 = E - G
+ G2 = E + G
+ A3 = F + A2
+ B3 = B2 - H
+ F2 = F - A2
+ H2 = B2 + H
+
+ data[i] = G2 + C2
+ data[i+stride] = A3 + H2
+ data[i+2*stride] = A3 - H2
+ data[i+3*stride] = E2 + D2
+ data[i+4*stride] = E2 - D2
+ data[i+5*stride] = F2 + B3
+ data[i+6*stride] = F2 - B3
+ data[i+7*stride] = G2 - C2
</pre><font face="Times New Roman">2D iDCT is performed first on rows, then columns (note order can affect lower bits!)
<br><font face="Courier New"><pre>
-</pre><font face="Times New Roman"><i>Note that we dequantized all coefficients to 4 times their real value. Since each coefficient is run through the iDCT twice (horizontal & vertical), the final values must be divided by 16.
+</pre><font face="Times New Roman"><i>(Note that we dequantized all coefficients to 4 times their real value. Since each coefficient is run through the iDCT twice (horizontal & vertical), the final values must be divided by 16.)
</i><br><font face="Courier New"><pre>
def idct(data):
-
for y in range(8):
idct_1D(data, y*8, 1);
@@ -573,10 +632,105 @@
for x in range(64):
data[x] = (data[x] + 8) >> 4 #add for rounding; /16 (remember dequant was *4!)
-</pre><font face="Times New Roman"><i>this routine converts intra-coded blocks of data into unsigned chars
+</pre><font face="Times New Roman"><b>loop filter
+</b><br><font face="Courier New"><pre>
+</pre><font face="Times New Roman">the Theora loop filter is run along every horizontal and vertical edge between blocks where one of the blocks is coded. In the keyframe case, this means every edge except the borders of the frame. For predicted frames, the only edges that are not filtered are those between two uncoded blocks (because they were filtered at some point previously, when the block was originally reconstructed)...
+<br><font face="Courier New"><pre>
+</pre><font face="Times New Roman"><i>clamping routine
+</i><br><font face="Courier New"><pre>
+def clampit(n, lo, hi):
+ if n < lo:
+ return lo
+ if n > hi:
+ return hi
+ return n
+
+</pre><font face="Times New Roman"><i>first, define an array of quality-dependent filter parameters:
+</i><br><font face="Courier New"><pre>
+loopfilter_array = [
+ 30, 25, 20, 20, 15, 15, 14, 14,
+ 13, 13, 12, 12, 11, 11, 10, 10,
+ 9, 9, 8, 8, 7, 7, 7, 7,
+ 6, 6, 6, 6, 5, 5, 5, 5,
+ 4, 4, 4, 4, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 ]
+
+</pre><font face="Times New Roman"><i>next, we define a step function with five linear segments:
+</i><br><font face="Courier New"><pre>
+def loopfunc(n):
+ global loopfilter_array
+ global quality_index #from the frame header
+ K = loopfilter_array[quality_index]
+ if (n <= -K*2) | (n >= K*2):
+ return 0
+ elif (n > -K*2) & (n < -K):
+ return -2*K - n
+ elif (n >= -K) & (n <= K):
+ return n
+ else:
+ return 2*K - n
+
+</pre><font face="Times New Roman"><i>now the 1D filter functions:
+</i><br><font face="Courier New"><pre>
+def filter_horiz(pixmap, x, y):
+ for i in range(8):
+
+ A = pixmap[x-2][y+i]
+ B = pixmap[x-1][y+i]
+ C = pixmap[x][y+i]
+ D = pixmap[x+1][y+i]
+
+ A = clampit(A, -128, 127)
+ B = clampit(B, -128, 127)
+ C = clampit(C, -128, 127)
+ D = clampit(D, -128, 127)
+
+ N = ( 4+(A - B*3 + C*3 - D)) >> 3
+ delta = loopfunc(N)
+
+ pixmap[x-1][y+i] = B + delta
+ pixmap[x][y+i] = C - delta
+
+def filter_vert(pixmap, x, y):
+
+ for i in range(8):
+
+ A = pixmap[x+i][y-2]
+ B = pixmap[x+i][y-1]
+ C = pixmap[x+i][y]
+ D = pixmap[x+i][y+1]
+
+ A = clampit(A, -128, 127)
+ B = clampit(B, -128, 127)
+ C = clampit(C, -128, 127)
+ D = clampit(D, -128, 127)
+
+ N = ( 4+(A - B*3 + C*3 - D)) >> 3
+ delta = loopfunc(N)
+
+ pixmap[x+i][y-1] = B + delta
+ pixmap[x+i][y] = C - delta
+
+</pre><font face="Times New Roman"><i>full filter (keyframe case only):
</i><br><font face="Courier New"><pre>
-def pixelize(data, w, h, dx, dy):
- pix = []
+def loopfilter(pixmap, w, h):
+ for y in range(h>>3):
+ for x in range(w>>3):
+ xx = x*8
+ yy = y*8
+ if xx > 0: #vertical if not on left edge
+ filter_horiz(pixmap, xx, yy)
+ if yy > 0: #horiz if not on top row
+ filter_vert(pixmap, xx, yy)
+
+</pre><font face="Times New Roman"><b>Pixel management routines
+</b><br><font face="Courier New"><pre>
+</pre><font face="Times New Roman"><i>this routine converts an array of 8x8 blocks of data into a pixel array
+</i><br><font face="Courier New"><pre>
+def blocks2pixels(data, w, h, dx, dy):
+ pix = [ [0 for y in range(h)] for x in range(w) ] #initialize 2D array, pix[w][h]
for y in range(h):
for x in range(w):
@@ -586,34 +740,41 @@
by = yy >> 3
ix = xx % 8
iy = yy % 8
- #print "pixelize: bx, by, ix, iy",bx,by,ix,iy
p = data[bx][by][ix + iy*8]
- p += 128
- if p < 0:
- p = 0
- if p > 255:
- p = 255
- pix.append(p)
+ pix[x][y] = p
+ return pix
-</pre><font face="Times New Roman"><i>return a linear list of suitably clamped & range-checked values from a map of blocks
-</i><br><font face="Courier New"><pre> return pix
+</pre><font face="Times New Roman"><i>one last helper -- turns a color map (integers with x, y coordinates) into a straight block array, clamped to 0-255:
+</i><br><font face="Courier New"><pre>
+def pixels2chars(pixels):
+ h = len(pixels[0])
+ w = len(pixels)
+
+ data = [] #initialze linear array width * height long
+
+ for y in range(h):
+ for x in range(w):
+ p = pixels[x][y]
+ p += 128
+ p = clampit(p, 0, 255)
+ data.append(p) #add it to the list
+ return data
</pre><font face="Times New Roman"><b> *** DECODING THE FRAME ***
</b><br><font face="Courier New"><pre>
-</pre><font face="Times New Roman"><i>ok, let's do it!
-</i><br><font face="Courier New"><pre>
+</pre><font face="Times New Roman">ok, let's do it!
+<br><font face="Courier New"><pre>
def decode_frame():
print
print "DECODING FRAME"
+ global quality_index, infoflag, tableflag
+
+ if (infoflag == 0) | (tableflag == 0): #if info & table not initialized
+ print "stream parameters not initialized -- missing info or table headers?"
+ abort()
</pre><font face="Times New Roman"><i>First, we decode the frame header:
</i><br><font face="Courier New"><pre>
- packet_type = readbit()
- print "packet_type:", packet_type
- if packet_type != 0:
- print "illegal packet type"
- abort()
-
is_predicted = readbit()
print "is_predicted:", is_predicted
quality_index = readbits(6)
@@ -645,7 +806,6 @@
</i><br><i>Also, as we go higher into the coefficient index, we will use different huffman tables:
</i><br><font face="Courier New"><pre>
for i in range(64): #For each coefficient index,
-
if i == 0: #get DC huffman tables for coeff=0
huff_Y = readbits(4)
huff_UV = readbits(4)
@@ -681,21 +841,21 @@
</pre><font face="Times New Roman"><i>if this is an end-of-block token, that means we have a run of blocks to mark as fully decoded:
</i><br><font face="Courier New"><pre>
if val == 'eob': #eob = End Of Block run
- xx = x
- for r in range(run): #clear <run> blocks (and wrap around!!)
+ xx = x #temporary block index starts with x
+ for r in range(run): #clear (run) blocks
done = len(coeffs[xx]) #this many coeffs are set in this block
remain = 64 - done #this many remain
- for j in range (remain):
- coeffs[xx].append(0) #zero out the rest of the block
- skipped=0 #keep a count of skipped blocks
- while len(coeffs[xx]) >i: #skip blocks that are coded up to this point or further
- xx = (xx+1) % blocks_tot #next block (and wrap around)
- skipped += 1
- if skipped >= blocks_tot: #quit if we're done (or we can loop forever)
- break
+ for j in range (remain): #for all remaining coeffs
+ coeffs[xx].append(0) #set to zero
+ ii = i #temporary coeff index starts with i
+ while (len(coeffs[xx]) >ii) and ii<64: #find next candidate block for eob treatment
+ xx += 1 #next block
+ if xx == blocks_tot: #if we wrapped around,
+ xx = 0 #back to block zero
+ ii += 1 #and next coeff
+
</pre><font face="Times New Roman"><i>otherwise the token represents a run of zeros followed by a value:
-</i><br><font face="Courier New"><pre>
- else: #zero run + value
+</i><br><font face="Courier New"><pre> else: #zero run + value
for r in range (run): #a run of zeros
coeffs[x].append(0)
coeffs[x].append(val) #followed by a val
@@ -743,81 +903,110 @@
comapV[x][y] = temp + []
</pre><font face="Times New Roman"><i>convert the image into a raw byte array of planar Y, V, U:
-</i><br><i>[note: this format differs from Mau's dumpvid, which lays out U & V interleaved rather than strict planar]
</i><br><font face="Courier New"><pre>
- pixY = pixelize(comapY, decode_width, decode_height, offset_x, offset_y)
- pixU = pixelize(comapU, decode_width>>1, decode_height>>1, offset_x>>1, offset_y>>1)
- pixV = pixelize(comapV, decode_width>>1, decode_height>>1, offset_x>>1, offset_y>>1)
+ pixY = blocks2pixels(comapY, decode_width, decode_height, offset_x, offset_y)
+ pixU = blocks2pixels(comapU, decode_width>>1, decode_height>>1, offset_x>>1, offset_y>>1)
+ pixV = blocks2pixels(comapV, decode_width>>1, decode_height>>1, offset_x>>1, offset_y>>1)
+
+</pre><font face="Times New Roman"><i>run loop filter:
+</i><br><font face="Courier New"><pre>
+ loopfilter(pixY, decode_width, decode_height)
+ loopfilter(pixU, decode_width>>1, decode_height>>1)
+ loopfilter(pixV, decode_width>>1, decode_height>>1)
</pre><font face="Times New Roman"><i>return the three color planes:
</i><br><font face="Courier New"><pre>
- return pixY, pixU, pixV
+ return pixels2chars(pixY), pixels2chars(pixU), pixels2chars(pixV)
</pre><font face="Times New Roman"><b><i>Decode Predicted Frame: THIS SECTION UNFINISHED
</b></i><br><font face="Courier New"><pre> else:
print "decoding interframe (NOT!)"
+ abort()
coding_scheme = readbits(3)
if coding_scheme == 0:
mode_alphabet = [] #define a list (think of it as an array)
for x in range(8):
mode_alphabet.append(readbits(3)) #add another mode to the list
-</pre><font face="Times New Roman"><i>end of definition for decode_frame()
+</pre><font face="Times New Roman"><i>--end of definition for decode_frame()
</i><br><font face="Courier New"><pre>
+</pre><font face="Times New Roman"><b>Parse Theora packets
+</b><br><font face="Courier New"><pre>
+</pre><font face="Times New Roman"><i>Define a function to parse the packet type & call appropriate functions. Returns either a string for header packets, or a tuple of Y, U, and V data for frames:
+</i><br><font face="Courier New"><pre>
+def decode_packet():
+ packet_type = readbit()
+ if packet_type == 0:
+ return decode_frame()
+ else:
+ return decode_header()
+
</pre><font face="Times New Roman"><h3><u>MAIN TEST SEQUENCE
</h3></u><br><font face="Courier New"><pre>
</pre><font face="Times New Roman">let's test our routines by parsing the stream headers and the first frame.
<br><font face="Courier New"><pre>
print
-print "DECODING STREAM HEADERS"
+print "THEORA SPEC PYTHON SCRIPT"
+print "Test: decoding first frame of", sys.argv[1]
+ret = ""
+
+while type(ret) == type(""): #string means stream header parsed
+ ret = decode_packet()
+ if type(ret) == type(""): #if it's a header packet,
+ print "header packet type:", ret #print the type (info, comment, tables)
+ if ret == "info":
+ print " version:", version_major, version_minor, version_subminor
+ print " encoded width:", encoded_width
+ print " encoded height:", encoded_height
+ print " decode width:", decode_width
+ print " decode height:", decode_height
+ print " X offset:", offset_x
+ print " Y offset:", offset_y
+ print " fps:", fps_numerator, "/", fps_denominator
+ print " aspect:", aspect_numerator, "/", aspect_denominator
+ print " colorspace:",
+ if colorspace == 0:
+ print " not specified"
+ elif colorspace == 1:
+ print " ITU 601"
+ elif colorspace == 2:
+ print " CIE 709"
+ else:
+ print " colorspace type not recognized"
+ print " target bitrate:", bitrate
+ print " target quality:", quality
+
+ elif ret == "comment":
+ print " vendor string:", vendor_string
+ print " comment length:", comment_string_len
+ elif ret == "table":
+ print "tables loaded"
+ else:
+ print "frame decoded"
-</pre><font face="Times New Roman"><i>Read and Verify Stream Headers:
-</i><br><font face="Courier New"><pre>
-read_page_header()
-read_info_header()
-read_page_header() #I know there's one around here
-read_comment_header() #but not here! (this is encoder-specific -- will be fixed)
-read_table_header()
-
-</pre><font face="Times New Roman"><i>print some useful information:
-</i><br><font face="Courier New"><pre>
-print "vendor string:", vendor_string
-print "comment length:", comment_string_len
-print "version:", version_major, version_minor, version_subminor
-print "encoded width:", encoded_width
-print "encoded height:", encoded_height
-print "decode width:", decode_width
-print "decode height:", decode_height
-print "X offset:", offset_x
-print "Y offset:", offset_y
-print "fps:", fps_numerator, "/", fps_denominator
-print "aspect:", aspect_numerator, "/", aspect_denominator
-print "colorspace:",
-if colorspace == 0:
- print "not specified"
-elif colorspace == 1:
- print "ITU 601"
-elif colorspace == 2:
- print "CIE 709"
-else:
- print "colorspace type not recognized, assuming unspecified"
- colorspace = 0
-print "target bitrate:", bitrate
-print "target quality:", quality
-
-</pre><font face="Times New Roman"><i> read the first frame...
-</i><br><font face="Courier New"><pre>
-read_page_header() #see prev. note about this function -- becomes read_packet()
-Y, U, V = decode_frame()
+</pre><font face="Times New Roman">'ret' should now have the first frame:
+<br><font face="Courier New"><pre>
+Y, U, V = ret
-</pre><font face="Times New Roman"><i>and write it to disk.
+</pre><font face="Times New Roman"><i>define a little routine to fix up the UV buffer the way we like:
</i><br><font face="Courier New"><pre>
-buf = array('B', Y+U+V)
-outfile = file("out.raw","wb")
+def interleave(U, V, w, h):
+ buf = []
+ for y in range(h):
+ for x in range(w):
+ buf.append( V[y*w + x] )
+ for x in range(w):
+ buf.append( U[y*w + x] )
+ return buf
+
+</pre><font face="Times New Roman">write data to disk:
+<br><font face="Courier New"><pre>
+buf = array('B', Y + interleave(U, V, decode_width/2, decode_height/2) )
+outfile = file(sys.argv[2],"wb")
outfile.write(buf)
-</pre><font face="Times New Roman"><i>that's all for now
-</i><br><font face="Courier New"><pre>print "done"
+</pre><font face="Times New Roman">that's all for now.
+<br><font face="Courier New"><pre>print "done"
<p><p>1.2 +412 -198 theora/doc/spec.py
Index: spec.py
===================================================================
RCS file: /usr/local/cvsroot/theora/doc/spec.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- spec.py 5 Jul 2003 23:18:14 -0000 1.1
+++ spec.py 15 Jul 2003 11:29:09 -0000 1.2
@@ -1,40 +1,85 @@
+#spec060 -- new stuff
+#spec061 -- finally -- bitwise equivalent to C code! (without loop filter)
+#spec062 -- FINALLY -- bitwise equvalent, even for TKAL! problem was dang page/packet stuff
+# this works sorta, but still needs to be revamped so Ogg stuff is not brittle
+# but at least it works with its own test data. Now gotta add loop filter
+#spec063 -- some tweaks
+#spec064 -- loop filter -- not working yet, but reorged pixel maps & stuff
+#spec065 -- loop filter working! (?) yes!
+#spec066 -- cleanup time -- derf's comments, other stuff (see unk.txt)
+# firster -- fix up UV ala C code
+#spec067 -- first -- fixing header parsing stuff
+#spec068 -- decode_packet() -- now we can do a proper main loop
+#spec069 -- ok, using correct logic for headers & frames
+#spec070 -- cleaned up for release as 0.070
+#spec071 -- take command line args, insist on info & table headers -- make it 0.071
+
##_Theora Bitstream Specification and Reference Decoder -- Theora 1.0
+#Document version: 0.071
#(c) 2003 Xiph Foundation, Dan Miller
#special thanks to various people at On2 Technologies for donating VP3, and to the folks at Xiph.org Foundation for
-#doing good things with it
+#doing good things with it. Particular shout outs to Mike Melansen, Tim Teriberry, Ralph Giles, Christopher
+#Montgomery, Mauricio Piacentini, and Jack Moffit (please let me know if I spelled your name wrong..)
+
+#This documentation and software are distributed under the terms of the BSD-style Theora license, as outlined in the
+#"COPYING" file in the root directory of this distribution. Please familiarize yourself with these terms before
+#distributing any of the documents in this directory.
-#This documentation is released under the yada yada open free gnu/BDS license etc.
+#Introduction
#Theora is a video codec. This is the spec.
+#State of this document
-#Introduction
+#This document is unfinished. It is a work in progress that is included in the Theora release for your edification.
+#Once it is complete and verified, it will hopefully become the canonical reference for Theora compatibility.
+
+#The most glaring deficiency is that presently the documentation and Python decoder only cover keyframes. We are
+#actively looking for volunteers to help us complete the work of fully documenting the Theora format. If you are
+#interested and believe you can help, please post a message to theora-dev at xiph.org, or contact jack at xiph.org or
+#danbmil99 at yahoo.com.
+
+#In addition to support for predicted frames, the Python script needs to be heavily error-protected. Presently
+#various illegal bitstreams will cause the program to go into an endless loop or crash in other unpredictable ways.
+#The specification should eventually be usable as a syntax checker that is able to detect and report on any possible
+#error condition within the bitstream. In addition to work on the code, we will need to generate a comprehensive test
+#suite of encoded files that exercise every aspect of the bitstream. Illegal files will also need to be generated to
+#test the error handling capacity of the script.
#About this document
#This document is The Theora Bitstream Specification and Reference Decoder. It is both an english language
#description of the Theora video bitstream, and an interpretable program in the Python programming language, which
#can be executed using a version 2.0 or later Python interpreter. More information about Python can be gleaned at
#www.python.org. When run as a Python script, this document will decode compliant Theora bitstreams, producing
-#uncompressed YUV files.
+#uncompressed YUV files. The YUV output format is identical to that used by
+#theora/win32/experimental/dumpvid/dump_vid.exe, which is as follows:
-#To invoke this document as a Python program: at the command prompt, type:
-#[prompt]> python spec.py testspec.ogg
+#For each frame, Y pixel data is output as unsigned characters, scanning left to right for each row of pixels
+#starting with the top row. The Y data is followed by interleaved V and U data, ie one scanline of V followed by one
+#scanline of U. This format allows raw data to be inspected visually as a monochrome image, with the V and U planes
+#situated directly below the Y plane.
-#The raw file will be saved as "out.raw"
+#To invoke this document as a Python program: at the command prompt, type:
+#[prompt]> python spec.py testspec.ogg out.raw
+#The program will attempt to open and decode 'testspec.ogg'. The raw decoded file will be saved as "out.raw"
#Formatting Conventions
-#There are two versions of this document: HTML, and Python. Both are created from the same source file.
+#There are three versions of this document: text, HTML, and Python. The HTML and Python versions are created from the
+#text file, spec.txt. While spec.txt is actually a legal Python script, the formatted version spec.py is more
+#readable as the comments have been reformatted with linefeeds and formatting characters have been stripped. To
+#create the HTML version spec.html, a simple hinting scheme is used to specify some rudimentary formatting (see
+#txt2html.py for details). The following commands will regenerate both files from the source file:
+
+#[prompt]> python txt2py.py spec.txt spec.py
+#[prompt]> python txt2html.py spec.txt spec.html
#In the HTML version, non-code sections are generally formatted using a variable-width font to distinguish them from
#code. Code and non-code can be interspersed, even within Python routines. In general, non-code blocks of text within
#routines will be italicized.
-#The Python version is a simple ascii text file intended for viewing in a source code editor with a fixed-width font.
-#Non-code sections are formatted as legal Python comments.
-
#Overview
#This document represents part of the overall specification package. The specification package includes the following
@@ -46,6 +91,8 @@
# * Verification Output Streams (uncompressed YUV data)
+#(Note: the following paragraph will not be considered in effect until this document is completed and verified - Ed.)
+
#A decoding application is Theora compliant IFF it can decode any Theora bitstream that is decodable with the
#Reference Decoder (this document), producing output that is bytewise equivalent. Several Verification Bitstreams and
#Verification Output Streams are included in the Specification Package for reference; the Verification Output Streams
@@ -55,7 +102,8 @@
#Please note: the Python code herein is written solely to facilitate the definition and compliance testing of Theora
#bitstreams. It is by design an extremely inefficient and poorly structured piece of code. Do not use this as a
-#template for real-world player applications. Instead, start with the C-based Theora decoder from CVS.
+#template for real-world player applications. Instead, start with the C-based Theora decoder available for download
+#at www.theora.org.
#The Theora Bitstream Specification does not cover encoders, except for the following sentence:
@@ -75,31 +123,78 @@
from array import array
from os import abort
+import sys
+
+#usage:
-#some globals & useful functions:
+if len(sys.argv) < 3:
+ print "usage: python spec.py infile outfile"
+ abort()
-oggfile = file("testspec.ogg","rb")
+#some globals & useful definitions:
+
+#oggfile = file("testspec.ogg","rb")
+oggfile = file(sys.argv[1],"rb")
oggstring = oggfile.read() #NOTE limited by memory constraints -- should use file I/O
oggindex = 0
+pagebytes = 0
+pagestart =0
oggbyte = 0
bitmask = 0
oggbuf = array('B',oggstring) #convert to an array of unsigned bytes
huffs = [] #this will contain list of huffman trees
+infoflag = 0 #initialization flags
+tableflag = 0
#Bitstream parsing routines
-#bit & byte ordering: For historical reasons, Ogg is generally little-endian, while Theora is big-endian when reading
-#values larger than 8 bits directly from the stream. For byte reads (on byte boundaries), it doesn't matter; both
-#schemes use the same bitpacking within a byte. These routines are intended primarily for reading the actual Theora
-#bitstream. However for testing purposes, we have to implement a bit of Ogg since the test files are Ogg formatted.
-#Note readlong() which is implemented to facilitate little-endian longword reads in the Ogg-aware routines.
+#Bit & byte ordering: typically, Ogg packs bits starting with the most significant bit to the least. For historical
+#reasons, Theora packs bits least significant bit first. In cases where values are byte-aligned (8 bit boundaries),
+#this only affects byte ordering. We do some Ogg parsing but it happens to be only on byte-aligned values, so we use
+#readbits(8) but reverse the byte order (See for instance readOgg32())
+
+#Note that in this specification we are assuming bytes are always 8 bit values. Future versions may support non-8-bit
+#platforms.
+
+#helpers:
+
+def flushpacket(): #flush bits between packets
+ global bitmask
+ bitmask = 0
+
+def flushpage(): #flush packet & disable paging for read_page_header()
+ global bitmask, pagebytes
+ bitmask = 0
+ pagebytes = 999999 #kluge - yuk
+
+#simple Ogg page header parsing routine. Note we are not checking CRC's; we are assuming Ogg data is not corrupt.
+
+def read_page_header():
+ global oggindex, pagebytes, pagestart
+ flushpage()
+ oggs = readstring(4) #get the putated 4-byte Ogg identifier
+ if oggs != "OggS":
+ print "invalid page data -- OggS =", oggs
+ abort()
+ oggindex += 10 #serialnum at offset 14
+ serialno = readOgg32()
+ oggindex += 8 #segment count at offset 26
+ segments = readbits(8)
+ bytes = 0
+ for i in range(segments):
+ bytes += readbits(8)
+ pagebytes = bytes
+ pagestart = oggindex
+
#this routine just grabs a byte from the input stream:
def readbyte(): #note: this is a low-level function to read
#a byte-aligned octet from the datastream.
#To read an arbitrarily aligned byte, use readbits(8)
- global oggindex
+ global oggindex,pagebytes
+ if oggindex >= pagestart+pagebytes:
+ read_page_header()
byte = oggbuf[oggindex]
oggindex += 1
return byte
@@ -109,8 +204,8 @@
def readbit():
global bitmask, oggbyte
if bitmask == 0:
- bitmask = 0x80
oggbyte = readbyte()
+ bitmask = 0x80
if oggbyte & bitmask:
bit = 1
else:
@@ -118,12 +213,9 @@
bitmask >>= 1
return bit
-def flushpage(): #Ogg pages are byte-aligned; need to flush after using
- global bitmask
- bitmask = 0
-
#readbits: our workhorse. Gets up to 32 bits from the stream
-#(note -- hi bit is first bit read! use readlong() or build up values through sequential byte reads for Ogg purposes)
+#(note -- hi bit is first bit read! use readOgg32() or build up values through sequential byte reads for Ogg
+#purposes)
def readbits(x):
ret = 0
@@ -140,9 +232,9 @@
s += chr(readbits(8))
return s
-#readlong reads a longword Ogg style:
+#readOgg32 reads a longword Ogg style:
-def readlong(): #different than readbits(32): byte order is reversed
+def readOgg32(): #different than readbits(32): byte order is reversed
return readbits(8) + (readbits(8) << 8) + (readbits(8) << 16) + (readbits(8) << 24)
@@ -159,9 +251,16 @@
#Note how this function is called recursively for each possible branch in the tree until all branches have bottomed
#out with complete bitstrings:
+hufftokens=0 #keep track of # of token strings -- 32 max
+
def read_hufftable(table):
+ global hufftokens
if readbit(): #if bit==1, this bitstring is complete
table.append( readbits(5) ) #next 5 bits = token number for this string
+ hufftokens += 1
+ if hufftokens > 32:
+ print "illegal huffman table, > 32 tokens"
+ abort()
else: #if bit was zero, we have two more entries defining
#the zero and one case for the next bit:
table.append([]) #add another pair of tables
@@ -186,11 +285,11 @@
#Each table contains the following five entries in this order:
-# base run length
-# number of extra run length bits (0 - 12)
-# base value
-# number of extra value bits (0 - 9)
-# number of extra sign bits (0 or 1)
+## base run length
+## number of extra run length bits (0 - 12)
+## base value
+## number of extra value bits (0 - 9)
+## number of extra sign bits (0 or 1)
token_array = [
[1, 0, 'eob', 0, 0],
@@ -235,8 +334,8 @@
def parsetoken(huf):
global token_array #(not strictly necessary for read-only in Python)
-
token = readtoken(huf) #read a token from the stream
+
table = token_array[token] #get our table of parameters for this token
run = table[0] #base run length
run_extra = table[1] #number of extra bits for run length
@@ -260,50 +359,22 @@
#note: string * 1 = string, so 'eob', 'zrl' are OK
-#routines to read & parse headers
-
-#simple Ogg page header parsing routine:
-
-def read_page_header():
- global oggindex
- flushpage()
- oggs = readstring(4) #get the putated 4-byte Ogg identifier
- if oggs != "OggS":
- print "invalid page data"
- abort()
- oggindex += 10 #serialnum at offset 14
- serialno = readlong()
- oggindex += 8 #segment count at offset 26
- segments = readbits(8)
- bytes = 0
- for i in range(segments):
- bytes += readbits(8)
+#routines to read & parse codec headers
#routine to parse the Theora info header:
-#[note: next three routines need to be rewritten so headers can come in any order]
def read_info_header():
global huffs, encoded_width, encoded_height, decode_width, decode_height, offset_x, offset_y
global fps_numerator, fps_denominator, aspect_numerator, aspect_denominator, quality, bitrate
- global version_major, version_minor, version_subminor, colorspace
-
- typeflag = readbits(8)
-
- if typeflag != 0x80: #first bit = 1; next 7 bits define header type.
- #for info header, 7 bit value = zero, so we have 0x80
- print "expected info header?"
- abort()
-
- cid = readstring(6) #codec ID
- if cid != "theora":
- print "Not a Theora header packet"
- abort()
+ global version_major, version_minor, version_subminor, colorspace, infoflag
version_major = readbits(8) #major & minor version must be exact match
if version_major != 3:
+ print "incompatible major version#"
abort()
version_minor = readbits(8)
if version_minor != 2:
+ print "incompatible minor version#"
abort()
version_subminor = readbits(8)
@@ -323,44 +394,24 @@
colorspace = readbits(8) #colorspace flag defines YUV to RGB mapping
bitrate = readbits(24) #target bitrate; not used for decode
quality = readbits(6) #target quality also not used for decode
-
+ infoflag = 1
#parse the comment header:
def read_comment_header():
global vendor_string, vendor_string_len, comment_string, comment_string_len
- typeflag = readbits(8)
-
- if typeflag != 0x81: #header type 1 = comment
- print "expected comment header? typeflag =",typeflag
- abort()
- cid = readstring(6)
- if cid != "theora":
- print "corrupted comment header?", cid
- abort()
-
- vendor_string_len = readlong()
+ vendor_string_len = readOgg32()
vendor_string = readstring(vendor_string_len)
- comment_string_len = readlong()
+ comment_string_len = readOgg32()
comment_string = readstring(comment_string_len)
#read & parse the table header:
def read_table_header():
- global scale_table_AC, scale_table_DC, Y_quantizer, UV_quantizer, IF_quantizer, frequency_counts
-
- typeflag = readbits(8)
-
- if typeflag != 0x82: #type 2 = table header
- print "expected table header? type = ", hex(typeflag)
- abort()
-
- cid = readstring(6)
- if cid != "theora":
- print "corrupted table header?", cid
- abort()
+ global scale_table_AC, scale_table_DC, Y_quantizer, UV_quantizer, IF_quantizer
+ global frequency_counts, hufftokens, tableflag
scale_table_AC = [] #64 possible quantizer scalers for AC coeffs
for x in range(64): scale_table_AC.append(readbits(16))
@@ -380,8 +431,38 @@
for x in range(80): #Read in huffman tables
huffs.append([])
+ hufftokens=0
read_hufftable(huffs[x])
+ tableflag = 1
+
+def decode_header():
+
+ header_type = readbits(7)
+
+ cid = readstring(6)
+ if cid != "theora":
+ print "not a theora stream header", cid
+ abort()
+
+ if header_type == 0:
+ read_info_header()
+ flushpacket()
+ return "info"
+
+ elif header_type == 1:
+ read_comment_header()
+ flushpacket()
+ return "comment"
+
+ elif header_type == 2:
+ read_table_header()
+ flushpacket()
+ return "table"
+
+ else:
+ print "unknown stream header type -- skipping"
+ return "unknown"
# Routines that decode video
@@ -447,7 +528,7 @@
p, q = hilbert[i] #nice Python syntax
xx = x*4 + p
yy = y*4 + q
- if (xx < w) & (yy < h): #skip stuff out of range
+ if (xx < w) & (yy < h): #skip stuff out of range
comap[xx][yy] = colist[ii] #if in range, get a coeff
ii += 1
return comap
@@ -481,7 +562,7 @@
if x == 0: #left column?
u = comap[0][y-1][0] #u = upper
ur = comap[1][y-1][0] #ur = upper-right
- p = u #[Shouldn't this be u*75 + ur*53??? but this works!]
+ p = u
comap[0][y][0] += p #add predictor to decoded value
else: #general case -- neither left column nor top row
@@ -525,7 +606,7 @@
# where sf = scale_table_DC[quality_index] for DC dequantizer
# scale_table_AC[quality_index] for AC dequantizer
-#Note that the dequantize routine also multiplies each coefficient by 4. This is to facilitate the iDCT later on.
+#(Note that the dequantize routine also multiplies each coefficient by 4. This is to facilitate the iDCT later on.)
def dequant(data, scaleDC, scaleAC, dqtable):
mul = int( (scaleDC * dqtable[0]) / 100 ) * 4
@@ -536,8 +617,9 @@
#ZIG-ZAG order
-#The coefficients in each 8x8 DCT coded block are layed out in 'zig-zag' order. The following table shows the order
-#in which the 64 coefficients are coded:
+#The coefficients in each 8x8 DCT coded block are layed out in 'zig-zag' order.
+
+#The following table shows the order in which the 64 coefficients are coded:
zigzag=[
0, 1, 5, 6, 14, 15, 27, 28,
@@ -568,47 +650,45 @@
#addition and subtraction can be performed normally.
-#First we define a one-dimensional iDCT:
+#First we define a one-dimensional iDCT. Note that there are many implementations of iDCT available. Theora
+#compatibility requires that the output of your iDCT routine be bitwise equivalent to the one outlined here:
def idct_1D(data, i, stride):
-#[where did these varnames come from? somebody make them instructive please]
-
A = Mul_fix(64277, data[i+stride]) + Mul_fix(12785, data[i+7*stride])
B = Mul_fix(12785, data[i+stride]) - Mul_fix(64277, data[i+7*stride])
C = Mul_fix(54491, data[i+3*stride]) + Mul_fix(36410, data[i+5*stride])
D = Mul_fix(54491, data[i+5*stride]) - Mul_fix(36410, data[i+3*stride])
- Ad = Mul_fix(46341, A - C)
- Bd = Mul_fix(46341, B - D)
- Cd = A + C
- Dd = B + D
+ A2 = Mul_fix(46341, A - C)
+ B2 = Mul_fix(46341, B - D)
+ C2 = A + C
+ D2 = B + D
E = Mul_fix(46341, data[i] + data[i+4*stride])
F = Mul_fix(46341, data[i] - data[i+4*stride])
G = Mul_fix(60547, data[i+2*stride]) + Mul_fix(25080, data[i+6*stride])
H = Mul_fix(25080, data[i+2*stride]) - Mul_fix(60547, data[i+6*stride])
- Ed = E - G
- Gd = E + G
- Add = F + Ad
- Bdd = Bd - H
- Fd = F - Ad
- Hd = Bd + H
-
- data[i] = Gd + Cd
- data[i+stride] = Add + Hd
- data[i+2*stride] = Add - Hd
- data[i+3*stride] = Ed + Dd
- data[i+4*stride] = Ed - Dd
- data[i+5*stride] = Fd + Bdd
- data[i+6*stride] = Fd - Bdd
- data[i+7*stride] = Gd - Cd
+ E2 = E - G
+ G2 = E + G
+ A3 = F + A2
+ B3 = B2 - H
+ F2 = F - A2
+ H2 = B2 + H
+
+ data[i] = G2 + C2
+ data[i+stride] = A3 + H2
+ data[i+2*stride] = A3 - H2
+ data[i+3*stride] = E2 + D2
+ data[i+4*stride] = E2 - D2
+ data[i+5*stride] = F2 + B3
+ data[i+6*stride] = F2 - B3
+ data[i+7*stride] = G2 - C2
#2D iDCT is performed first on rows, then columns (note order can affect lower bits!)
-#Note that we dequantized all coefficients to 4 times their real value. Since each coefficient is run through the
-#iDCT twice (horizontal & vertical), the final values must be divided by 16.
+#(Note that we dequantized all coefficients to 4 times their real value. Since each coefficient is run through the
+#iDCT twice (horizontal & vertical), the final values must be divided by 16.)
def idct(data):
-
for y in range(8):
idct_1D(data, y*8, 1);
@@ -618,10 +698,108 @@
for x in range(64):
data[x] = (data[x] + 8) >> 4 #add for rounding; /16 (remember dequant was *4!)
-#this routine converts intra-coded blocks of data into unsigned chars
+#loop filter
+
+#the Theora loop filter is run along every horizontal and vertical edge between blocks where one of the blocks is
+#coded. In the keyframe case, this means every edge except the borders of the frame. For predicted frames, the only
+#edges that are not filtered are those between two uncoded blocks (because they were filtered at some point
+#previously, when the block was originally reconstructed)...
+
+#clamping routine
+
+def clampit(n, lo, hi):
+ if n < lo:
+ return lo
+ if n > hi:
+ return hi
+ return n
+
+#first, define an array of quality-dependent filter parameters:
+
+loopfilter_array = [
+ 30, 25, 20, 20, 15, 15, 14, 14,
+ 13, 13, 12, 12, 11, 11, 10, 10,
+ 9, 9, 8, 8, 7, 7, 7, 7,
+ 6, 6, 6, 6, 5, 5, 5, 5,
+ 4, 4, 4, 4, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 ]
+
+#next, we define a step function with five linear segments:
+
+def loopfunc(n):
+ global loopfilter_array
+ global quality_index #from the frame header
+ K = loopfilter_array[quality_index]
+ if (n <= -K*2) | (n >= K*2):
+ return 0
+ elif (n > -K*2) & (n < -K):
+ return -2*K - n
+ elif (n >= -K) & (n <= K):
+ return n
+ else:
+ return 2*K - n
+
+#now the 1D filter functions:
+
+def filter_horiz(pixmap, x, y):
+ for i in range(8):
+
+ A = pixmap[x-2][y+i]
+ B = pixmap[x-1][y+i]
+ C = pixmap[x][y+i]
+ D = pixmap[x+1][y+i]
+
+ A = clampit(A, -128, 127)
+ B = clampit(B, -128, 127)
+ C = clampit(C, -128, 127)
+ D = clampit(D, -128, 127)
+
+ N = ( 4+(A - B*3 + C*3 - D)) >> 3
+ delta = loopfunc(N)
+
+ pixmap[x-1][y+i] = B + delta
+ pixmap[x][y+i] = C - delta
+
+def filter_vert(pixmap, x, y):
+
+ for i in range(8):
+
+ A = pixmap[x+i][y-2]
+ B = pixmap[x+i][y-1]
+ C = pixmap[x+i][y]
+ D = pixmap[x+i][y+1]
+
+ A = clampit(A, -128, 127)
+ B = clampit(B, -128, 127)
+ C = clampit(C, -128, 127)
+ D = clampit(D, -128, 127)
+
+ N = ( 4+(A - B*3 + C*3 - D)) >> 3
+ delta = loopfunc(N)
-def pixelize(data, w, h, dx, dy):
- pix = []
+ pixmap[x+i][y-1] = B + delta
+ pixmap[x+i][y] = C - delta
+
+#full filter (keyframe case only):
+
+def loopfilter(pixmap, w, h):
+ for y in range(h>>3):
+ for x in range(w>>3):
+ xx = x*8
+ yy = y*8
+ if xx > 0: #vertical if not on left edge
+ filter_horiz(pixmap, xx, yy)
+ if yy > 0: #horiz if not on top row
+ filter_vert(pixmap, xx, yy)
+
+#Pixel management routines
+
+#this routine converts an array of 8x8 blocks of data into a pixel array
+
+def blocks2pixels(data, w, h, dx, dy):
+ pix = [ [0 for y in range(h)] for x in range(w) ] #initialize 2D array, pix[w][h]
for y in range(h):
for x in range(w):
@@ -631,18 +809,26 @@
by = yy >> 3
ix = xx % 8
iy = yy % 8
- #print "pixelize: bx, by, ix, iy",bx,by,ix,iy
p = data[bx][by][ix + iy*8]
- p += 128
- if p < 0:
- p = 0
- if p > 255:
- p = 255
- pix.append(p)
-
-#return a linear list of suitably clamped & range-checked values from a map of blocks
+ pix[x][y] = p
return pix
+#one last helper -- turns a color map (integers with x, y coordinates) into a straight block array, clamped to 0-255:
+
+def pixels2chars(pixels):
+ h = len(pixels[0])
+ w = len(pixels)
+
+ data = [] #initialze linear array width * height long
+
+ for y in range(h):
+ for x in range(w):
+ p = pixels[x][y]
+ p += 128
+ p = clampit(p, 0, 255)
+ data.append(p) #add it to the list
+ return data
+
# *** DECODING THE FRAME ***
#ok, let's do it!
@@ -650,15 +836,14 @@
def decode_frame():
print
print "DECODING FRAME"
+ global quality_index, infoflag, tableflag
+
+ if (infoflag == 0) | (tableflag == 0): #if info & table not initialized
+ print "stream parameters not initialized -- missing info or table headers?"
+ abort()
#First, we decode the frame header:
- packet_type = readbit()
- print "packet_type:", packet_type
- if packet_type != 0:
- print "illegal packet type"
- abort()
-
is_predicted = readbit()
print "is_predicted:", is_predicted
quality_index = readbits(6)
@@ -691,7 +876,6 @@
#Also, as we go higher into the coefficient index, we will use different huffman tables:
for i in range(64): #For each coefficient index,
-
if i == 0: #get DC huffman tables for coeff=0
huff_Y = readbits(4)
huff_UV = readbits(4)
@@ -727,20 +911,20 @@
#if this is an end-of-block token, that means we have a run of blocks to mark as fully decoded:
if val == 'eob': #eob = End Of Block run
- xx = x
- for r in range(run): #clear <run> blocks (and wrap around!!)
+ xx = x #temporary block index starts with x
+ for r in range(run): #clear (run) blocks
done = len(coeffs[xx]) #this many coeffs are set in this block
remain = 64 - done #this many remain
- for j in range (remain):
- coeffs[xx].append(0) #zero out the rest of the block
- skipped=0 #keep a count of skipped blocks
- while len(coeffs[xx]) >i: #skip blocks that are coded up to this point or further
- xx = (xx+1) % blocks_tot #next block (and wrap around)
- skipped += 1
- if skipped >= blocks_tot: #quit if we're done (or we can loop forever)
- break
-#otherwise the token represents a run of zeros followed by a value:
+ for j in range (remain): #for all remaining coeffs
+ coeffs[xx].append(0) #set to zero
+ ii = i #temporary coeff index starts with i
+ while (len(coeffs[xx]) >ii) and ii<64: #find next candidate block for eob treatment
+ xx += 1 #next block
+ if xx == blocks_tot: #if we wrapped around,
+ xx = 0 #back to block zero
+ ii += 1 #and next coeff
+#otherwise the token represents a run of zeros followed by a value:
else: #zero run + value
for r in range (run): #a run of zeros
coeffs[x].append(0)
@@ -789,81 +973,111 @@
comapV[x][y] = temp + []
#convert the image into a raw byte array of planar Y, V, U:
-#[note: this format differs from Mau's dumpvid, which lays out U & V interleaved rather than strict planar]
- pixY = pixelize(comapY, decode_width, decode_height, offset_x, offset_y)
- pixU = pixelize(comapU, decode_width>>1, decode_height>>1, offset_x>>1, offset_y>>1)
- pixV = pixelize(comapV, decode_width>>1, decode_height>>1, offset_x>>1, offset_y>>1)
+ pixY = blocks2pixels(comapY, decode_width, decode_height, offset_x, offset_y)
+ pixU = blocks2pixels(comapU, decode_width>>1, decode_height>>1, offset_x>>1, offset_y>>1)
+ pixV = blocks2pixels(comapV, decode_width>>1, decode_height>>1, offset_x>>1, offset_y>>1)
+
+#run loop filter:
+
+ loopfilter(pixY, decode_width, decode_height)
+ loopfilter(pixU, decode_width>>1, decode_height>>1)
+ loopfilter(pixV, decode_width>>1, decode_height>>1)
#return the three color planes:
- return pixY, pixU, pixV
+ return pixels2chars(pixY), pixels2chars(pixU), pixels2chars(pixV)
#Decode Predicted Frame: THIS SECTION UNFINISHED
else:
print "decoding interframe (NOT!)"
+ abort()
coding_scheme = readbits(3)
if coding_scheme == 0:
mode_alphabet = [] #define a list (think of it as an array)
for x in range(8):
mode_alphabet.append(readbits(3)) #add another mode to the list
-#end of definition for decode_frame()
+#--end of definition for decode_frame()
+
+
+#Parse Theora packets
+#Define a function to parse the packet type & call appropriate functions. Returns either a string for header packets,
+#or a tuple of Y, U, and V data for frames:
+
+def decode_packet():
+ packet_type = readbit()
+ if packet_type == 0:
+ return decode_frame()
+ else:
+ return decode_header()
#MAIN TEST SEQUENCE
#let's test our routines by parsing the stream headers and the first frame.
print
-print "DECODING STREAM HEADERS"
+print "THEORA SPEC PYTHON SCRIPT"
+print "Test: decoding first frame of", sys.argv[1]
+ret = ""
+
+while type(ret) == type(""): #string means stream header parsed
+ ret = decode_packet()
+ if type(ret) == type(""): #if it's a header packet,
+ print "header packet type:", ret #print the type (info, comment, tables)
+ if ret == "info":
+ print " version:", version_major, version_minor, version_subminor
+ print " encoded width:", encoded_width
+ print " encoded height:", encoded_height
+ print " decode width:", decode_width
+ print " decode height:", decode_height
+ print " X offset:", offset_x
+ print " Y offset:", offset_y
+ print " fps:", fps_numerator, "/", fps_denominator
+ print " aspect:", aspect_numerator, "/", aspect_denominator
+ print " colorspace:",
+ if colorspace == 0:
+ print " not specified"
+ elif colorspace == 1:
+ print " ITU 601"
+ elif colorspace == 2:
+ print " CIE 709"
+ else:
+ print " colorspace type not recognized"
+ print " target bitrate:", bitrate
+ print " target quality:", quality
+
+ elif ret == "comment":
+ print " vendor string:", vendor_string
+ print " comment length:", comment_string_len
+ elif ret == "table":
+ print "tables loaded"
+ else:
+ print "frame decoded"
-#Read and Verify Stream Headers:
+#'ret' should now have the first frame:
-read_page_header()
-read_info_header()
-read_page_header() #I know there's one around here
-read_comment_header() #but not here! (this is encoder-specific -- will be fixed)
-read_table_header()
-
-#print some useful information:
-
-print "vendor string:", vendor_string
-print "comment length:", comment_string_len
-print "version:", version_major, version_minor, version_subminor
-print "encoded width:", encoded_width
-print "encoded height:", encoded_height
-print "decode width:", decode_width
-print "decode height:", decode_height
-print "X offset:", offset_x
-print "Y offset:", offset_y
-print "fps:", fps_numerator, "/", fps_denominator
-print "aspect:", aspect_numerator, "/", aspect_denominator
-print "colorspace:",
-if colorspace == 0:
- print "not specified"
-elif colorspace == 1:
- print "ITU 601"
-elif colorspace == 2:
- print "CIE 709"
-else:
- print "colorspace type not recognized, assuming unspecified"
- colorspace = 0
-print "target bitrate:", bitrate
-print "target quality:", quality
-
-# read the first frame...
+Y, U, V = ret
-read_page_header() #see prev. note about this function -- becomes read_packet()
-Y, U, V = decode_frame()
+#define a little routine to fix up the UV buffer the way we like:
+
+def interleave(U, V, w, h):
+ buf = []
+ for y in range(h):
+ for x in range(w):
+ buf.append( V[y*w + x] )
+ for x in range(w):
+ buf.append( U[y*w + x] )
+ return buf
-#and write it to disk.
+#write data to disk:
-buf = array('B', Y+U+V)
-outfile = file("out.raw","wb")
+buf = array('B', Y + interleave(U, V, decode_width/2, decode_height/2) )
+outfile = file(sys.argv[2],"wb")
outfile.write(buf)
-#that's all for now
+#that's all for now.
print "done"
<p><p>1.2 +4 -2 theora/doc/testspec.ogg
Index: testspec.ogg
===================================================================
RCS file: /usr/local/cvsroot/theora/doc/testspec.ogg,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
Binary files /tmp/cvsfbIG9h and /tmp/cvsM25n6p differ
<p><p>1.1 theora/doc/spec.txt
Index: spec.txt
===================================================================
#spec060 -- new stuff
#spec061 -- finally -- bitwise equivalent to C code! (without loop filter)
#spec062 -- FINALLY -- bitwise equvalent, even for TKAL! problem was dang page/packet stuff
# this works sorta, but still needs to be revamped so Ogg stuff is not brittle
# but at least it works with its own test data. Now gotta add loop filter
#spec063 -- some tweaks
#spec064 -- loop filter -- not working yet, but reorged pixel maps & stuff
#spec065 -- loop filter working! (?) yes!
#spec066 -- cleanup time -- derf's comments, other stuff (see unk.txt)
# firster -- fix up UV ala C code
#spec067 -- first -- fixing header parsing stuff
#spec068 -- decode_packet() -- now we can do a proper main loop
#spec069 -- ok, using correct logic for headers & frames
#spec070 -- cleaned up for release as 0.070
#spec071 -- take command line args, insist on info & table headers -- make it 0.071
####_Theora Bitstream Specification and Reference Decoder -- Theora 1.0
##Document version: 0.071
#/(c) 2003 Xiph Foundation, Dan Miller
#/special thanks to various people at On2 Technologies for donating VP3, and to the folks at Xiph.org Foundation for doing good things with it. Particular shout outs to Mike Melansen, Tim Teriberry, Ralph Giles, Christopher Montgomery, Mauricio Piacentini, and Jack Moffit (please let me know if I spelled your name wrong..)
#/This documentation and software are distributed under the terms of the BSD-style Theora license, as outlined in the "COPYING" file in the root directory of this distribution. Please familiarize yourself with these terms before distributing any of the documents in this directory.
###_Introduction
#Theora is a video codec. This is the spec.
##_State of this document
#This document is unfinished. It is a work in progress that is included in the Theora release for your edification. Once it is complete and verified, it will hopefully become the canonical reference for Theora compatibility.
#The most glaring deficiency is that presently the documentation and Python decoder only cover keyframes. We are actively looking for volunteers to help us complete the work of fully documenting the Theora format. If you are interested and believe you can help, please post a message to theora-dev at xiph.org, or contact jack at xiph.org or danbmil99 at yahoo.com.
#In addition to support for predicted frames, the Python script needs to be heavily error-protected. Presently various illegal bitstreams will cause the program to go into an endless loop or crash in other unpredictable ways. The specification should eventually be usable as a syntax checker that is able to detect and report on any possible error condition within the bitstream. In addition to work on the code, we will need to generate a comprehensive test suite of encoded files that exercise every aspect of the bitstream. Illegal files will also need to be generated to test the error handling capacity of the script.
##_About this document
#This document is The Theora Bitstream Specification and Reference Decoder. It is both an english language description of the Theora video bitstream, and an interpretable program in the Python programming language, which can be executed using a version 2.0 or later Python interpreter. More information about Python can be gleaned at www.python.org. When run as a Python script, this document will decode compliant Theora bitstreams, producing uncompressed YUV files. The YUV output format is identical to that used by theora/win32/experimental/dumpvid/dump_vid.exe, which is as follows:
#For each frame, Y pixel data is output as unsigned characters, scanning left to right for each row of pixels starting with the top row. The Y data is followed by interleaved V and U data, ie one scanline of V followed by one scanline of U. This format allows raw data to be inspected visually as a monochrome image, with the V and U planes situated directly below the Y plane.
#To invoke this document as a Python program: at the command prompt, type:
#*[prompt]> python spec.py testspec.ogg out.raw
#The program will attempt to open and decode 'testspec.ogg'. The raw decoded file will be saved as "out.raw"
##_Formatting Conventions
#There are three versions of this document: text, HTML, and Python. The HTML and Python versions are created from the text file, spec.txt. While spec.txt is actually a legal Python script, the formatted version spec.py is more readable as the comments have been reformatted with linefeeds and formatting characters have been stripped. To create the HTML version spec.html, a simple hinting scheme is used to specify some rudimentary formatting (see txt2html.py for details). The following commands will regenerate both files from the source file:
#*[prompt]> python txt2py.py spec.txt spec.py
#*[prompt]> python txt2html.py spec.txt spec.html
#In the HTML version, non-code sections are generally formatted using a variable-width font to distinguish them from code. Code and non-code can be interspersed, even within Python routines. In general, non-code blocks of text within routines will be italicized.
##_Overview
#This document represents part of the overall specification package. The specification package includes the following elements:
#* * Theora Bitstream Specification and Reference Decoder (this document)
#* * Verification Bitstreams (compressed data)
#* * Verification Output Streams (uncompressed YUV data)
##/(Note: the following paragraph will not be considered in effect until this document is completed and verified - Ed.)
#A decoding application is Theora compliant IFF it can decode any Theora bitstream that is decodable with the Reference Decoder (this document), producing output that is bytewise equivalent. Several Verification Bitstreams and Verification Output Streams are included in the Specification Package for reference; the Verification Output Streams were produced using this document as a Python script. However, it is understood that a compliant decoder must be capable of decoding any legal Theora bitstream, not just those included in the Specification Package. A legal Theora bitstream is any bitstream that can be decoded by this document.
#Please note: the Python code herein is written solely to facilitate the definition and compliance testing of Theora bitstreams. It is by design an extremely inefficient and poorly structured piece of code. Do not use this as a template for real-world player applications. Instead, start with the C-based Theora decoder available for download at www.theora.org.
#The Theora Bitstream Specification does not cover encoders, except for the following sentence:
#_/An encoder is Theora compliant if it can produce a compressed bitstream that the Verification Decoder can decode.
#Note that this could be an application that produces nothing but black frames. The quality and scope of a Theora compliant encoder are entirely defined by the application domain for that product. If it produces a syntactically correct Theora bitstream, it is by definition a Theora encoder. The rest is up to you.
<p>###_Theora Bitstream Specification
#A Theora bitstream consists of header packet(s), followed by video packets. A decoder must receive all valid header packets before playing video. (note that this means if you wish to play a Theora stream from an arbitrary point, you need a mechanism to acquire the header information for that stream before commencing playback).
#Before we define our first routine, a little housekeeping for Python:
from array import array
from os import abort
import sys
#/usage:
if len(sys.argv) < 3:
print "usage: python spec.py infile outfile"
abort()
#/some globals & useful definitions:
#oggfile = file("testspec.ogg","rb")
oggfile = file(sys.argv[1],"rb")
oggstring = oggfile.read() #NOTE limited by memory constraints -- should use file I/O
oggindex = 0
pagebytes = 0
pagestart =0
oggbyte = 0
bitmask = 0
oggbuf = array('B',oggstring) #convert to an array of unsigned bytes
huffs = [] #this will contain list of huffman trees
infoflag = 0 #initialization flags
tableflag = 0
##_Bitstream parsing routines
#Bit & byte ordering: typically, Ogg packs bits starting with the most significant bit to the least. For historical reasons, Theora packs bits least significant bit first. In cases where values are byte-aligned (8 bit boundaries), this only affects byte ordering. We do some Ogg parsing but it happens to be only on byte-aligned values, so we use readbits(8) but reverse the byte order (See for instance readOgg32())
#Note that in this specification we are assuming bytes are always 8 bit values. Future versions may support non-8-bit platforms.
#/helpers:
def flushpacket(): #flush bits between packets
global bitmask
bitmask = 0
def flushpage(): #flush packet & disable paging for read_page_header()
global bitmask, pagebytes
bitmask = 0
pagebytes = 999999 #kluge - yuk
#/simple Ogg page header parsing routine. Note we are not checking CRC's; we are assuming Ogg data is not corrupt.
def read_page_header():
global oggindex, pagebytes, pagestart
flushpage()
oggs = readstring(4) #get the putated 4-byte Ogg identifier
if oggs != "OggS":
print "invalid page data -- OggS =", oggs
abort()
oggindex += 10 #serialnum at offset 14
serialno = readOgg32()
oggindex += 8 #segment count at offset 26
segments = readbits(8)
bytes = 0
for i in range(segments):
bytes += readbits(8)
pagebytes = bytes
pagestart = oggindex
<p>#/this routine just grabs a byte from the input stream:
def readbyte(): #note: this is a low-level function to read
#a byte-aligned octet from the datastream.
#To read an arbitrarily aligned byte, use readbits(8)
global oggindex,pagebytes
if oggindex >= pagestart+pagebytes:
read_page_header()
byte = oggbuf[oggindex]
oggindex += 1
return byte
#/These are used during the bulk of Theora stream parsing:
def readbit():
global bitmask, oggbyte
if bitmask == 0:
oggbyte = readbyte()
bitmask = 0x80
if oggbyte & bitmask:
bit = 1
else:
bit = 0
bitmask >>= 1
return bit
#/readbits: our workhorse. Gets up to 32 bits from the stream
#/(note -- hi bit is first bit read! use readOgg32() or build up values through sequential byte reads for Ogg purposes)
def readbits(x):
ret = 0
for i in range(x):
ret <<= 1
ret += readbit()
return ret
#/readstring reads a string of 8-bit unsigned chars:
def readstring(x):
s = ''
for i in range(x):
s += chr(readbits(8))
return s
#/readOgg32 reads a longword Ogg style:
def readOgg32(): #different than readbits(32): byte order is reversed
return readbits(8) + (readbits(8) << 8) + (readbits(8) << 16) + (readbits(8) << 24)
##_entropy coding routines
#Certain values in Theora (such as DCT coefficients) are encoded using a context-sensitive Huffman scheme based on 32 possible token values. Each token value has an associated set of extra bits that are bitpacked immediately following the primary huffman string. The binary decision trees (80 of them) necessary for decoding are in the table header.
##Set up the Huffman tables
#Huffman tables are encoded in compressed form using the following algorithm:
#/Note how this function is called recursively for each possible branch in the tree until all branches have bottomed out with complete bitstrings:
hufftokens=0 #keep track of # of token strings -- 32 max
def read_hufftable(table):
global hufftokens
if readbit(): #if bit==1, this bitstring is complete
table.append( readbits(5) ) #next 5 bits = token number for this string
hufftokens += 1
if hufftokens > 32:
print "illegal huffman table, > 32 tokens"
abort()
else: #if bit was zero, we have two more entries defining
#the zero and one case for the next bit:
table.append([]) #add another pair of tables
table.append([])
read_hufftable(table[0]) #with an entry for zero
read_hufftable(table[1]) #and one for one
##read a token
#/Again, we use recursion to parse the bits until we have a complete string:
def readtoken(huf):
if type(huf[0]) == type(0): #integer means we have a value
return huf[0] #return token value
else:
if readbit(): #read a bit, recurse into subtable 0 or 1
return readtoken(huf[1]) #case for bit=1
else:
return readtoken(huf[0]) #case for bit=0
##define an array of information tables for each token
#/Each table contains the following five entries in this order:
#*# base run length
#*# number of extra run length bits (0 - 12)
#*# base value
#*# number of extra value bits (0 - 9)
#*# number of extra sign bits (0 or 1)
token_array = [
[1, 0, 'eob', 0, 0],
[2, 0, 'eob', 0, 0],
[3, 0, 'eob', 0, 0],
[4, 2, 'eob', 0, 0],
[8, 3, 'eob', 0, 0],
[16, 4, 'eob', 0, 0],
[0, 12, 'eob', 0, 0],
[0, 3, 0, 0, 0],
[0, 6, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, -1, 0, 0],
[0, 0, 2, 0, 0],
[0, 0, -2, 0, 0],
[0, 0, 3, 0, 1],
[0, 0, 4, 0, 1],
[0, 0, 5, 0, 1],
[0, 0, 6, 0, 1],
[0, 0, 7, 1, 1],
[0, 0, 9, 2, 1],
[0, 0, 13, 3, 1],
[0, 0, 21, 4, 1],
[0, 0, 37, 5, 1],
[0, 0, 69, 9, 1],
[1, 0, 1, 0, 1],
[2, 0, 1, 0, 1],
[3, 0, 1, 0, 1],
[4, 0, 1, 0, 1],
[5, 0, 1, 0, 1],
[6, 2, 1, 0, 1],
[10, 3, 1, 0, 1],
[1, 0, 2, 1, 1],
[2, 1, 2, 1, 1] ]
##parse the tokens
#/this function returns a run length & value based on the token & extended bits:
def parsetoken(huf):
global token_array #(not strictly necessary for read-only in Python)
token = readtoken(huf) #read a token from the stream
table = token_array[token] #get our table of parameters for this token
run = table[0] #base run length
run_extra = table[1] #number of extra bits for run length
value = table[2] #actual value
val_extra = table[3] #number of extra value bits
sign_extra = table[4] #number of sign bits
sign = 1
if sign_extra:
if readbit():
sign = -1 #if there's a sign bit, get it. 1 means negative
#note that value may be negative to begin with, in
#which case there are no extra value or sign bits
if val_extra:
value += readbits(val_extra) #get extra value bits
if run_extra:
run += readbits(run_extra) #get extra run bits
return [run, value * sign] #return run length and value
#note: string * 1 = string, so 'eob', 'zrl' are OK
<p>##_routines to read & parse codec headers
#/routine to parse the Theora info header:
def read_info_header():
global huffs, encoded_width, encoded_height, decode_width, decode_height, offset_x, offset_y
global fps_numerator, fps_denominator, aspect_numerator, aspect_denominator, quality, bitrate
global version_major, version_minor, version_subminor, colorspace, infoflag
version_major = readbits(8) #major & minor version must be exact match
if version_major != 3:
print "incompatible major version#"
abort()
version_minor = readbits(8)
if version_minor != 2:
print "incompatible minor version#"
abort()
version_subminor = readbits(8)
encoded_width = readbits(16) << 4 #encoded width & height are in block units of 16x16
encoded_height = readbits(16) << 4
decode_width = readbits(24) #decode width & height are in actual pixels
decode_height = readbits(24)
offset_x = readbits(8) #offset for cropping if decode != full encoded frame
offset_y = readbits(8)
fps_numerator = readbits(32) #frames per second encoded as a fraction
fps_denominator = readbits(32)
aspect_numerator = readbits(24) #aspect not used now
aspect_denominator = readbits(24)
readbits(5) #force keyframe frequency flag -- not used for decode
colorspace = readbits(8) #colorspace flag defines YUV to RGB mapping
bitrate = readbits(24) #target bitrate; not used for decode
quality = readbits(6) #target quality also not used for decode
infoflag = 1
#/parse the comment header:
def read_comment_header():
global vendor_string, vendor_string_len, comment_string, comment_string_len
vendor_string_len = readOgg32()
vendor_string = readstring(vendor_string_len)
comment_string_len = readOgg32()
comment_string = readstring(comment_string_len)
<p>#/read & parse the table header:
def read_table_header():
global scale_table_AC, scale_table_DC, Y_quantizer, UV_quantizer, IF_quantizer
global frequency_counts, hufftokens, tableflag
scale_table_AC = [] #64 possible quantizer scalers for AC coeffs
for x in range(64): scale_table_AC.append(readbits(16))
scale_table_DC = [] #64 possible quantizer scalers for DC coeffs
#Note this is unrelated to 64 coeffs in an 8x8 block!
for x in range(64): scale_table_DC.append(readbits(16))
Y_quantizer = [] #quantizers for intra Y coeff (this IS about 8x8 blocks!)
for x in range(64): Y_quantizer.append(readbits(8))
UV_quantizer = [] #quantizers for intra U or V coeff
for x in range(64): UV_quantizer.append(readbits(8))
IF_quantizer = [] #quantizers for interframe coeffs (Y, U, or V)
for x in range(64): IF_quantizer.append(readbits(8))
for x in range(80): #Read in huffman tables
huffs.append([])
hufftokens=0
read_hufftable(huffs[x])
tableflag = 1
def decode_header():
header_type = readbits(7)
cid = readstring(6)
if cid != "theora":
print "not a theora stream header", cid
abort()
if header_type == 0:
read_info_header()
flushpacket()
return "info"
elif header_type == 1:
read_comment_header()
flushpacket()
return "comment"
elif header_type == 2:
read_table_header()
flushpacket()
return "table"
else:
print "unknown stream header type -- skipping"
return "unknown"
##_ Routines that decode video
#/[NOTE: for now, these routines only handle keyframes. We may modify or add routines to support interframe data]
#/[NOTE: each frame of video resides in a single Ogg page.]
#/[NOTE: that's crap. each frame of video resides in a logical Ogg packet. pagination is irrelevant.]
##Hilbert ordering
#All data in Theora is organized into 8x8 blocks. When encoding the data, these blocks are further grouped into 'super-blocks' of 16 blocks each, and encoded in 'Hilbert' order. Each super-block consists of up to 16 blocks encoded in the following order:
#* X -> X X -> X
#* | ^
#* v |
#* X <- X X <- X
#* | ^
#* v |
#* X X -> X X
#* | ^ | ^
#* v | v |
#* X -> X X -> X
#(thanks to Mike Melanson for the diagram)
#If any block is not coded (due to clipping, for instance -- encoded images can include partial super-blocks) the pattern continues until the next coded block is hit. Each pixel plane -- Y, V, and U -- are encoded using their own pattern of superblocks.
#By way of example: if a plane consisted of 32x16 pixels, only the top half of the Hilbert pattern would be used. If the 8 8x8 blocks in this example are labled in this way:
#* A B C D
#* E F G H
#then they will be encoded in the following order: A, B, F, E, H, G, C, D.
<p>#/the following array & function are used to 'de-hilbertize' the data. [note: this is a keyframe-only routine right now]
hilbert = [
[0,0], [1,0], [1,1], [0,1],
[0,2], [0,3], [1,3], [1,2],
[2,2], [2,3], [3,3], [3,2],
[3,1], [2,1], [2,0], [3,0] ]
def de_hilbert(w, h, colist): #width, height, coefficient list
sbw = int( (w+3) / 4) #super-block width (width in sb's)
sbh = int( (h+3) / 4) #super-block height (height in sb's)
ii = 0
comap = []
for x in range(w): #initialize coefficient map
comap.append([])
for y in range(h):
comap[x].append([])
for y in range(sbh):
for x in range(sbw):
for i in range(16):
p, q = hilbert[i] #nice Python syntax
xx = x*4 + p
yy = y*4 + q
if (xx < w) & (yy < h): #skip stuff out of range
comap[xx][yy] = colist[ii] #if in range, get a coeff
ii += 1
return comap
##decoding the DC coefficients
#The DC values are simply the zero-order coefficients of each 8x8 block. These values tend to have more entropy than most AC components, so in addition to quantization, it is desirable to use delta coding to reduce the data requirement of encoding them.
#Theora uses a scheme where each encoded DC value is in fact a difference between a predicted value and the actual value. Since the blocks are coded in raster order, the predicted value can be any combination of DC values of blocks to the left, up, upper left, and upper right.
#/routine to do DC prediction on a single color plane:
def DCpredict(comap, w, h):
#/first row is straight delta coding:
l = 0 #l = DC coeff to my left; init to zero
for x in range(w):
l += comap[x][0][0]
comap[x][0][0] = l
#/now the rest:
for y in range(h):
for x in range(w):
if y>0: #already got the first row
if x == 0: #left column?
u = comap[0][y-1][0] #u = upper
ur = comap[1][y-1][0] #ur = upper-right
p = u
comap[0][y][0] += p #add predictor to decoded value
else: #general case -- neither left column nor top row
l = comap[x-1][y][0] #l = left
ul = comap[x-1][y-1][0] #ul = upper-left
u = comap[x][y-1][0] #u = upper
p = (l*29 + u*29 - ul*26) #compute weighted predictor
if p < 0:
p += 31 #round towards zero
p >>= 5 #shift by weight multiplier
if abs(p-u) > 128: #range checking
p = u;
if abs(p-l) > 128:
p = l;
if abs(p-ul) > 128:
p = ul;
comap[x][y][0] += p #add predictor to decoded value
<p>##Dequantization logic
#/(thanks again to Mike Melanson for this exposition)
#_Setting Up The Dequantizers
#Theora has three static tables for dequantizing fragments-- one for intra Y fragments, one for intra C fragments, and one for inter Y or C fragments. In the following code, these tables are loaded as Y_quantizer[], UV_quantizer[], and IF_quantizer[] (see definition for read_table_header below). However, these tables are adjusted according to the value of quality_index.
#quality_index is an index into 2 64-element tables: scale_table_DC[] and scale_table_AC[]. Each dequantizer from the three dequantization tables is adjusted by the appropriate scale factor according to this formula:
#* Scale dequantizers:
#* dequantizer * sf
#* ----------------
#* 100
#* where sf = scale_table_DC[quality_index] for DC dequantizer
#* scale_table_AC[quality_index] for AC dequantizer
#/(Note that the dequantize routine also multiplies each coefficient by 4. This is to facilitate the iDCT later on.)
def dequant(data, scaleDC, scaleAC, dqtable):
mul = int( (scaleDC * dqtable[0]) / 100 ) * 4
for x in range(64):
if x>0:
mul = int( (scaleAC * dqtable[x]) / 100 ) * 4
data[x] *= mul
##ZIG-ZAG order
#The coefficients in each 8x8 DCT coded block are layed out in 'zig-zag' order.
#/The following table shows the order in which the 64 coefficients are coded:
zigzag=[
0, 1, 5, 6, 14, 15, 27, 28,
2, 4, 7, 13, 16, 26, 29, 42,
3, 8, 12, 17, 25, 30, 41, 43,
9, 11, 18, 24, 31, 40, 44, 53,
10, 19, 23, 32, 39, 45, 52, 54,
20, 22, 33, 38, 46, 51, 55, 60,
21, 34, 37, 47, 50, 56, 59, 61,
35, 36, 48, 49, 57, 58, 62, 63]
#/this routine remaps the coefficients to their original order:
def unzig(data,un):
for x in range(64):
un[x] = data[zigzag[x]]
##inverse DCT (iDCT)
#Once coefficients are re-ordered and dequantized, the iDCT is performed on the 8x8 matrix to produce the actual pixel values (or differentials for predicted blocks).
#Theora's particular choice of iDCT computation involves intermediate values that are calculated using 32 bit, fixed-point arithmetic. Multiplication is defined as follows (assuming 32-bit integer parameters):
def Mul_fix(a, b):
return (a * b) >> 16
#addition and subtraction can be performed normally.
#/First we define a one-dimensional iDCT. Note that there are many implementations of iDCT available. Theora compatibility requires that the output of your iDCT routine be bitwise equivalent to the one outlined here:
def idct_1D(data, i, stride):
A = Mul_fix(64277, data[i+stride]) + Mul_fix(12785, data[i+7*stride])
B = Mul_fix(12785, data[i+stride]) - Mul_fix(64277, data[i+7*stride])
C = Mul_fix(54491, data[i+3*stride]) + Mul_fix(36410, data[i+5*stride])
D = Mul_fix(54491, data[i+5*stride]) - Mul_fix(36410, data[i+3*stride])
A2 = Mul_fix(46341, A - C)
B2 = Mul_fix(46341, B - D)
C2 = A + C
D2 = B + D
E = Mul_fix(46341, data[i] + data[i+4*stride])
F = Mul_fix(46341, data[i] - data[i+4*stride])
G = Mul_fix(60547, data[i+2*stride]) + Mul_fix(25080, data[i+6*stride])
H = Mul_fix(25080, data[i+2*stride]) - Mul_fix(60547, data[i+6*stride])
E2 = E - G
G2 = E + G
A3 = F + A2
B3 = B2 - H
F2 = F - A2
H2 = B2 + H
data[i] = G2 + C2
data[i+stride] = A3 + H2
data[i+2*stride] = A3 - H2
data[i+3*stride] = E2 + D2
data[i+4*stride] = E2 - D2
data[i+5*stride] = F2 + B3
data[i+6*stride] = F2 - B3
data[i+7*stride] = G2 - C2
#2D iDCT is performed first on rows, then columns (note order can affect lower bits!)
#/(Note that we dequantized all coefficients to 4 times their real value. Since each coefficient is run through the iDCT twice (horizontal & vertical), the final values must be divided by 16.)
def idct(data):
for y in range(8):
idct_1D(data, y*8, 1);
for x in range(8):
idct_1D(data, x, 8);
for x in range(64):
data[x] = (data[x] + 8) >> 4 #add for rounding; /16 (remember dequant was *4!)
##loop filter
#the Theora loop filter is run along every horizontal and vertical edge between blocks where one of the blocks is coded. In the keyframe case, this means every edge except the borders of the frame. For predicted frames, the only edges that are not filtered are those between two uncoded blocks (because they were filtered at some point previously, when the block was originally reconstructed)...
#/clamping routine
def clampit(n, lo, hi):
if n < lo:
return lo
if n > hi:
return hi
return n
#/first, define an array of quality-dependent filter parameters:
loopfilter_array = [
30, 25, 20, 20, 15, 15, 14, 14,
13, 13, 12, 12, 11, 11, 10, 10,
9, 9, 8, 8, 7, 7, 7, 7,
6, 6, 6, 6, 5, 5, 5, 5,
4, 4, 4, 4, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 ]
#/next, we define a step function with five linear segments:
def loopfunc(n):
global loopfilter_array
global quality_index #from the frame header
K = loopfilter_array[quality_index]
if (n <= -K*2) | (n >= K*2):
return 0
elif (n > -K*2) & (n < -K):
return -2*K - n
elif (n >= -K) & (n <= K):
return n
else:
return 2*K - n
#/now the 1D filter functions:
def filter_horiz(pixmap, x, y):
for i in range(8):
A = pixmap[x-2][y+i]
B = pixmap[x-1][y+i]
C = pixmap[x][y+i]
D = pixmap[x+1][y+i]
A = clampit(A, -128, 127)
B = clampit(B, -128, 127)
C = clampit(C, -128, 127)
D = clampit(D, -128, 127)
N = ( 4+(A - B*3 + C*3 - D)) >> 3
delta = loopfunc(N)
pixmap[x-1][y+i] = B + delta
pixmap[x][y+i] = C - delta
def filter_vert(pixmap, x, y):
for i in range(8):
A = pixmap[x+i][y-2]
B = pixmap[x+i][y-1]
C = pixmap[x+i][y]
D = pixmap[x+i][y+1]
A = clampit(A, -128, 127)
B = clampit(B, -128, 127)
C = clampit(C, -128, 127)
D = clampit(D, -128, 127)
N = ( 4+(A - B*3 + C*3 - D)) >> 3
delta = loopfunc(N)
pixmap[x+i][y-1] = B + delta
pixmap[x+i][y] = C - delta
#/full filter (keyframe case only):
def loopfilter(pixmap, w, h):
for y in range(h>>3):
for x in range(w>>3):
xx = x*8
yy = y*8
if xx > 0: #vertical if not on left edge
filter_horiz(pixmap, xx, yy)
if yy > 0: #horiz if not on top row
filter_vert(pixmap, xx, yy)
##Pixel management routines
#/this routine converts an array of 8x8 blocks of data into a pixel array
def blocks2pixels(data, w, h, dx, dy):
pix = [ [0 for y in range(h)] for x in range(w) ] #initialize 2D array, pix[w][h]
for y in range(h):
for x in range(w):
xx = x+dx
yy = y+dy
bx = xx >> 3
by = yy >> 3
ix = xx % 8
iy = yy % 8
p = data[bx][by][ix + iy*8]
pix[x][y] = p
return pix
#/one last helper -- turns a color map (integers with x, y coordinates) into a straight block array, clamped to 0-255:
def pixels2chars(pixels):
h = len(pixels[0])
w = len(pixels)
data = [] #initialze linear array width * height long
for y in range(h):
for x in range(w):
p = pixels[x][y]
p += 128
p = clampit(p, 0, 255)
data.append(p) #add it to the list
return data
## *** DECODING THE FRAME ***
#ok, let's do it!
def decode_frame():
print
print "DECODING FRAME"
global quality_index, infoflag, tableflag
if (infoflag == 0) | (tableflag == 0): #if info & table not initialized
print "stream parameters not initialized -- missing info or table headers?"
abort()
#/First, we decode the frame header:
is_predicted = readbit()
print "is_predicted:", is_predicted
quality_index = readbits(6)
print "quality_index =", quality_index
scalefactor_AC = scale_table_AC[quality_index] #(ThisFrameQualityValue in C)
print "scalefactor_AC =", scalefactor_AC
scalefactor_DC = scale_table_DC[quality_index]
print "scalefactor_DC =", scalefactor_DC
if is_predicted == 0: #0 = keyframe, 1 = interframe
#/OK, this is a keyframe. That means we just have 'intra' coded blocks.
print "decoding keyframe"
keyframe_type = readbit() #keyframe type always == 1 (DCT) (for now)
readbits(2) #2 unused bits
#/compute some values based on width & height:
blocks_Y = int( (encoded_height*encoded_width)/64 ) #Y blocks coded
blocks_UV = int(blocks_Y / 2)
blocks_U = int(blocks_UV / 2)
blocks_V = blocks_U
blocks_tot = int(blocks_Y * 1.5) #Y and UV blocks coded
#/initialize a map of coefficients. For each coded block, we will eventually have 64:
global coeffs
coeffs = [ [] for x in range(blocks_tot) ]
#/Theora encodes each coefficient for every block in sequence. IE first we decode all the DC coefficients; then coefficient #1, then #2, and so on.
#/Also, as we go higher into the coefficient index, we will use different huffman tables:
for i in range(64): #For each coefficient index,
if i == 0: #get DC huffman tables for coeff=0
huff_Y = readbits(4)
huff_UV = readbits(4)
elif i == 1:
huff_Y = readbits(4)+16 #get AC huff tables at 1, 6, 15, and 28
huff_UV = readbits(4)+16
elif i == 6:
huff_Y += 16
huff_UV += 16
elif i == 15:
huff_Y += 16
huff_UV += 16
elif i == 28:
huff_Y += 16
huff_UV += 16
#/now, for every block, decode our coefficient:
for x in range(blocks_tot):
if x < blocks_Y: #if we're in the Y plane,
huff = huff_Y
else:
huff = huff_UV
#/first check whether this coefficient was already decoded (Because of an end-of-block or other run):
if len(coeffs[x]) <= i: #if this coeff has not been set
#/if not, get a token:
run, val = parsetoken(huffs[huff])
#/if this is an end-of-block token, that means we have a run of blocks to mark as fully decoded:
if val == 'eob': #eob = End Of Block run
xx = x #temporary block index starts with x
for r in range(run): #clear (run) blocks
done = len(coeffs[xx]) #this many coeffs are set in this block
remain = 64 - done #this many remain
for j in range (remain): #for all remaining coeffs
coeffs[xx].append(0) #set to zero
ii = i #temporary coeff index starts with i
while (len(coeffs[xx]) >ii) and ii<64: #find next candidate block for eob treatment
xx += 1 #next block
if xx == blocks_tot: #if we wrapped around,
xx = 0 #back to block zero
ii += 1 #and next coeff
#/otherwise the token represents a run of zeros followed by a value:
else: #zero run + value
for r in range (run): #a run of zeros
coeffs[x].append(0)
coeffs[x].append(val) #followed by a val
#/now 'de-hilbertize' coefficient blocks:
Yheight = int(encoded_height/8)
Ywidth = int(encoded_width/8)
UVheight = int(Yheight/2)
UVwidth = int(Ywidth/2)
global comapY, comapU, comapV
comapY = de_hilbert(Ywidth, Yheight, coeffs)
comapU = de_hilbert(UVwidth, UVheight, coeffs[blocks_Y:])
comapV = de_hilbert(UVwidth, UVheight, coeffs[(blocks_Y+blocks_U):])
#/next, we need to reverse the DC prediction-based delta coding:
DCpredict(comapY, Ywidth, Yheight)
DCpredict(comapV, UVwidth, UVheight)
DCpredict(comapU, UVwidth, UVheight)
#/finally reorder, dequantize, and iDCT all the coefficients, for each color plane:
temp = [0 for x in range(64)] #temporary array
for y in range(Yheight):
for x in range(Ywidth):
unzig (comapY[x][y], temp)
dequant(temp, scalefactor_DC, scalefactor_AC, Y_quantizer)
idct(temp)
comapY[x][y] = temp + [] #Python quirk -- force assignment by copy (not reference)
for y in range(UVheight):
for x in range(UVwidth):
unzig (comapU[x][y], temp)
dequant(temp, scalefactor_DC, scalefactor_AC, UV_quantizer)
idct(temp)
comapU[x][y] = temp + []
for y in range(UVheight):
for x in range(UVwidth):
unzig (comapV[x][y], temp)
dequant(temp, scalefactor_DC, scalefactor_AC, UV_quantizer)
idct(temp)
comapV[x][y] = temp + []
#/convert the image into a raw byte array of planar Y, V, U:
pixY = blocks2pixels(comapY, decode_width, decode_height, offset_x, offset_y)
pixU = blocks2pixels(comapU, decode_width>>1, decode_height>>1, offset_x>>1, offset_y>>1)
pixV = blocks2pixels(comapV, decode_width>>1, decode_height>>1, offset_x>>1, offset_y>>1)
#/run loop filter:
loopfilter(pixY, decode_width, decode_height)
loopfilter(pixU, decode_width>>1, decode_height>>1)
loopfilter(pixV, decode_width>>1, decode_height>>1)
#/return the three color planes:
return pixels2chars(pixY), pixels2chars(pixU), pixels2chars(pixV)
##/Decode Predicted Frame: THIS SECTION UNFINISHED
else:
print "decoding interframe (NOT!)"
abort()
coding_scheme = readbits(3)
if coding_scheme == 0:
mode_alphabet = [] #define a list (think of it as an array)
for x in range(8):
mode_alphabet.append(readbits(3)) #add another mode to the list
#/--end of definition for decode_frame()
<p>##Parse Theora packets
#/Define a function to parse the packet type & call appropriate functions. Returns either a string for header packets, or a tuple of Y, U, and V data for frames:
def decode_packet():
packet_type = readbit()
if packet_type == 0:
return decode_frame()
else:
return decode_header()
###_MAIN TEST SEQUENCE
#let's test our routines by parsing the stream headers and the first frame.
print
print "THEORA SPEC PYTHON SCRIPT"
print "Test: decoding first frame of", sys.argv[1]
ret = ""
while type(ret) == type(""): #string means stream header parsed
ret = decode_packet()
if type(ret) == type(""): #if it's a header packet,
print "header packet type:", ret #print the type (info, comment, tables)
if ret == "info":
print " version:", version_major, version_minor, version_subminor
print " encoded width:", encoded_width
print " encoded height:", encoded_height
print " decode width:", decode_width
print " decode height:", decode_height
print " X offset:", offset_x
print " Y offset:", offset_y
print " fps:", fps_numerator, "/", fps_denominator
print " aspect:", aspect_numerator, "/", aspect_denominator
print " colorspace:",
if colorspace == 0:
print " not specified"
elif colorspace == 1:
print " ITU 601"
elif colorspace == 2:
print " CIE 709"
else:
print " colorspace type not recognized"
print " target bitrate:", bitrate
print " target quality:", quality
elif ret == "comment":
print " vendor string:", vendor_string
print " comment length:", comment_string_len
elif ret == "table":
print "tables loaded"
else:
print "frame decoded"
#'ret' should now have the first frame:
Y, U, V = ret
#/define a little routine to fix up the UV buffer the way we like:
def interleave(U, V, w, h):
buf = []
for y in range(h):
for x in range(w):
buf.append( V[y*w + x] )
for x in range(w):
buf.append( U[y*w + x] )
return buf
#write data to disk:
buf = array('B', Y + interleave(U, V, decode_width/2, decode_height/2) )
outfile = file(sys.argv[2],"wb")
outfile.write(buf)
#that's all for now.
print "done"
<p><p><p>1.1 theora/doc/testspec2.ogg
Index: testspec2.ogg
===================================================================
OggS
ëQ2ÿÿÿÿÿÿÿÿÿÿtheora#
<p><p><p><p><p><p>
(3=:<7
(9E83WP>%:DmgM#7 at Qhq\1 at NWgyxeH\_bpdgc/ccccBcccc8ccccc/Bcccccccccccccccccccccccccccccccccccccc ( (0 (0@ (0@@ (0@@@ (0@@@` (0@@@`(0@@@`f'|
ÁÕ{rÌEº7À~åD½Á±úÕR4Ì®ÅØ ÈÁíLÎaµ«
ªR¼ûwÉ;i]±/G«Pld¼~rîbWG´y' ÷UHAæ©÷UH®Æ3ÒÚ<ë¹!ÀÊÖco?ð¼ó·ü'¦ÑçRDÆêÖfSPk¾-!Gözñ±Ì»#@îP{Grmw°W*¾$ÿE¬r¸D;_î!iÅ 7NJäP÷o:õTó8N¬Ø.7]¤Éâ»ußÿdÆòØ)³À´ë;,VcÊFDÒɵÿÔ¥¹ÙX|'ÒÉ´x-à3êèVZcÉÿÔ¥¹ ¼ìÔEÿØù} ¹ìú[`p&MtÅæNïUH$×ëܽN&j
γaÔ7+
?ÅG~pªÑdÄ£_
ÉÉ¥ÚG¸sqîlémE(®pÅëYE$_Ûw!6Ô}á?úd¶P#YYºóíIæ~ÚD¹°èZd÷NøÏuR,¬_(}ïÚÿצxF"eÃÜÚ.;Óx`ëY¨ê|º¡N+[rvôDÒGù¦FæήÀó§qmçÐ
jihpåM+Ú$ó\7̹öØÆà#Û÷qg´K'T§3'Ð-a¸;6
&öY"k
íç+Åf`åÔzd¸ÿ©ZÂ
UºsÖYix¦m¬G'Ñ=¢púêU²
¦m¬ÆþðvF~aÂÛ
àncâÏùSPµã³ÚcIk,:¾²ÅÞà=Æäÿ®åE d6Õ3L塺²Ä?#=÷Ш4ÌÛ\XM?hØSPã©9ûto8R:¿æò>´!£¿ÐÑÚ¤M.åéeeÞn)Üó
¿PÝÊðM+mtÎ<»cAedïz¨RøbH6Õ+I³Ê[¸uè~a+üW`«»APÞ¥0k¢à·§ÞKÉ͵JÒláÿ)ÔF²±½JPðô$^Á!¶©g/þÀ9Nºß«x±cÊU8$/JÀm©Í3ÆäöQs
1¿ôüÀ¦¡jï ÌÒfÚË#î´/z8ûq¹ÐÄÉ1¦mµF /GÊ>¬°··ð#q<9U$O´²±ßQ¸
mY4Ï/ïãôë¦mµ0¡7Í$hOeúªDO-aß\8
É×ýîUIedBsᶪ^¸Ëû3Ëc^ñJ§Ö6Õ+I¤Î<y!¾äÝ°eËî)©Pò®À_ß-P`H%i1¶¹åMÞ»üSPïçVÀ=#nBü½##me&iWÑÀYYP©¨#|¸¼2¦rµÇ ¢ÍÞçïÊGÓúª¿wÅÂä«Æ¶ÔÂfXÿoA¼^×ÿwÇ
UÃ,ZfmªfÏG): G
ªJQ»ê"G¹%¦aãmL±iÊÏáì5RYXã~É\Nm«ÿX´ÌºÖõéÉ!<µMA
Î'0$4ÌÛYrÇ»
÷
#EÎz¿NH
µ2¦r±ÂûªS
û¢
0¡Èû=úßtåÖé"Ý¥·9îû'
'
1!ã£zÞÄ0(#öh6ÓÌóbì#"HJ¨ÈÒر[ØJÑmÉóAEçÝà ¡T×9¡(
ìÔõóà6ó{N¢5
[_#N)9§¥.ÀVÿÆ~û³êÈ?§
F
:x©*c#Ãç]läDzùv4Ñýkͧnê·½hå}¶ï¿È½KS]5~.òm¨ß2c\5ÞØ`Dh-¿¥!_?(¨ºc¡÷,ÿ6<k<;²d¯º
ËãfÃ=pË ·ïBì¼:ãìýÀà8ïC0tÒd_p :
9|4IxKèðþ ³PÏ}A¼³WNÆlQw<½_7ñ
õmºÉ³eEÔ6!ÜÃH³O溺}>^ÿFî³½zߪνdÌ"5ÐzɸëóTç]ü9«djâjk ³_
«WÞ½s\û½ÿú"]ÿGA±G*Â&S}
§yz¯Å6ÿ{ÑûôëîWûRÍmÞ½[|èQ©ÁÐÝpîéÜÞ·2ϱcäº%üZÕmÓOnATzÕ ©6ªñGhÐãRÓócT¡êÃjT%ÞõîÆýó ï+MÍ£/Ó½CD·÷ÐÞï}
Ã}º´õe×w ºtýnÞ×ç×®¿P*}ïëåï´5NK¦§OÍä å*Y®mWãm¨ èÆ«Ù¸Î/*<«±¡@V#QÐPID!Kpjø+â£×tm/Z<ª(¸#Ú?GæN|]ïÀç%Àrª+IÁ
$3Î
ÑðñpåDvÀJ'
àqÒHÒý¤¹õH#)ê%;ÑÑ°½5\¡lÊ ä:ç2dîܧI\ï:KèÕû÷ÎëÒ(?ædÝVºú7-ýÄ]ÞIïië¥$é¸?8A+(è$CÞOå4÷*êV~¹{£NÎEòvm¹Ú)ÃÝkw:®:MóæmÎïÚ í=HýU2beÞý×ÎTW:Ú.t¥·¤òµAvBéèTùõÝE¾¼¸¨û»vwç¹½;¼EêMq^Þ6^ç`uF¦}Ö{»ÕBÏ
¾ÏGO¢jÿ¨tÀ.ùj
]DÒ=jlá)©Áïúì>ðJp<Hr8ðúMM<©dlòi*úlnfP
¨óîô"
:oD¦ =d[¦K^4r°ó @ XsAh+t´XAf0"»a`° ÎÀ6«
#2N*Ó¦fcb¢²ÚH«í*&Â,LOâH¼è¥d©IÀÍ#e$ü|^!÷ ýâñ¢£ß¿u°©OggS
6yïºÅ"VÊäQÉè±,þlé¢õ³p+Ù à&'×lnk«ÚÀûD'Øû_¥B\ýl1ÍR.Ußbhæ2I'X®xÜßeLÜ̱ÍÊr{Ñ1
(É6èùÓ(o¤?Éê;,b·ô3j±R9³|´È5ʨ68EQÈEáåsþn$ç=vxmÙ±ñ[¨ÔÑõÉßX1sAÐrzâ{>É8Õ $jÿÀhÓ ¤¡"
övVK`³ÕúÆÉÐ|×|7T¸3Q×STåÇSÅo¦|
AÀ©)0X'zÅ$%§Él5È$ÃΣÖ\}¦¦¸2¹À©t=:Q>»ýÁMÔ|Ð'4éi¬¨2¸'ðýÓïÆ÷ÞÐÓ×îFÕZ®³×ª¡ÊyR×ß|~jMUQU;Ú©ôS®:ðåáam3SϦ¿í^©ÕXÞ«±ø°h~,È1í~?"Oó?}¢ðSWÄl¡HÎgùYb£8m¦
£Ý\¢ç [Pd ïÈeµè*dãt"`¾RÇT[Ñä]¡ã<T*8N8ÌL(³z2SªôlÆîëØlÆæ&¢u«ßvlÄÂe$«SùI$,&Ñ (ssÄN«þqxbÉFR¤.c~Ál»
<p>1.1 theora/doc/testspec2.raw
Index: testspec2.raw
===================================================================
Zf;eT-fBRPNOTXZ\^``abbccbcec`YSKBBGHE<2+'&&&&&&''()+-1452/-+)((*+'"%.8=>BKYbfghjlnoqrqqqssrqpnmljhfeba_\YXYVPG>96642222341,,2?NZ_YL>6343,',35Ad
qO;?@65;97;94/--,*)'&&&)-27>FLRTSRPONNONKIHFDBA;.'$! !#$%$#$',39>?>>>?@BGLRUUTUUUSQPQTZ^_\WSPOOPRUX\dggd]SICBDEEC?;7322100/.*))))))($#######! !#%%##%&''&# JOU=JY?PYVRQSVVWXYYXWVUVWY[[XTOICDIJF=3+'&&&&&&''()+.1341.,*(((**&"%.7=>CMYbfghjkmoqqqpqrrrponmlihfeba_\YXYVQH?:8642112321.-.14:><5/-045.)+16FkgK9=?55;;:=:3-*(&#" #).39?EJLMLLKLMNMKIGEB>;5*%#!!"#%%%$##&+28<>=<==>@DJPSSTUUTSQPPSX\]ZVSQPPQSVX^glkhaWMFAABA?<85100/..-,(''''''&$#######! "$$""#%&%%#BFZ]nb\UQQPNMLLKIGECCFIKMLJGEDGKMH?5-'&&&&&&'()+,.021/-+)('())&#%,6<?FOZbffhjkmopqqppqqqonmlkihfeba_]YYYWRJC>97531110//11.*$#$%#$',252+*.7Mt[E7;=55<=>@<3*%#!$'*/49<?@ABCEHKLIHFC>82-%"! !#%&''%$"!$)06;<;;::;=AFLPRSTTTRQONQVYZXTSRSSSTVX]fkjf_VME?==<:752.-,,+**)%$$$$$$$########! !## "#$$#!
_n«ÿ¤jêßc\SMIFB?<<;9865569<>??>?CGLMI at 5-'&&&&&&')+,.//0/,+)'&&'('&$%+3;@IR\befgiklnoppoppponmkjjihfeba_][ZZXSMGB;863100.+,143/*&###$(,143/*+7RvN?6:;54:?BC>4)! !$'*,.1346:>BDDEDA;2*% !#%&(('%# #(/59;:9888:=CHLQSSTSQPNNPSVWUSSTUTTTVWZ_a`\VNGA;986420.+))((''%#"""""""########! !!!"##" /MW¯§·_TKD?<72/...////./135668=CHJG?5-'&&&&&&'*,./0/-,)('&%%&'&%%%)1:BLU]cdegijkmoooonoonlkjiihhfeba_]\[[XUPKE>96310/-,-0231/,'$$&)-2662,*7Ql}C<8::648=BD at 5( !$%')-148=@B@:/% !#$&&&%#!#(/59;:97778;@EIORSSRQONNORTUTSSUVUTSTTUWWVSOID?9641/.-+)''&%%$#! !"#######"! !"##" !""#"!KeGIÕüZJIA;751-***+,----,,--./06<BEC<3,'&&&&&&'+-/10.+)'&%$$%&&%%&%(.9COX_bcdfijkmnoonnmmlkjhghhhfeba_^\\[YVSOJ@:731/...//0/-,("!&-4996.*5JYZ?;;<:6349 at C@6*!! "%(-4:>?:0% "#""#"!#)06;<;98767:>CHOQRRRPNNOPRSTTTTVVTRQQQPONNMJHE at 941.,++*(&&%%$$"! !"#####
##"! "#$$#!!#%'(*)'#PMFY¼ÝYD at 95431.....---...,+**++.3:??91+'&&&&&&'+.121.*'%$###$%%$%&&&-8DRZ`cccfiijlnnnmmmlkjigfghhfeba_^]]\ZWUSMB;741/.--.1430,)# "+49:91+2AC;9<?>;7315<B at 8-$! "#&**(&$! !%-5<?<2' $+28<>=;9777:>BGNQRRQPNNQRSTUUUUVURPNMMJEBBBBBA?830,**+*(&&%%$$#!!!!!!!""#######"! "#%&%%# "%),/10-("Q0]ÝgË@@4/2530221/.-,-/.-+)(((*.4784/*&%&&''(*,.01/,(&$####$%%$%'&%*7EU[_a``bdghjklmnnlkjhgfedihec_^\[[[[ZXVTOE?;7420.(-47983-)&!!(05883,/86/5>A>963028>>8/'%%%%%&(*-242/,(%#! '.8><4)"$*28=>=;9779;?CHORSSSQPPQSUUVVVUUSPNMKJE=88788:951.+*)**(&%%$$$$#"!!!!""####""""! !"#$%%$" %*/12441+#JaÕðèý`D2,2751110.-,,---,*)('()+-//.,)&%%')*+,,-,+)'&$$$$##$$$$$&'#$4JW[[YWVUW[\\]`ejkihhfda_``_[VRPOORSUVVTRPKGC>:64/+3:99;5+'$ %,16751/128;?=95311047860+)''&%&),057763/+'#! &19:2(!!'.6;<;86679=BFKQTUVVUTRRSUWWWUTTQONMLHB;731/
020.+**))))'&$"!"$%$"! "$%&%$$#""! !"!!""""""! $,2553365/&=+_v>9ZMH at 306:5100/---..-,,+)(((+,,,,,,*&%&(*+--,+*('%$$$$$$$$$$%$&'""3JXZWSOKHGHIILRZchhggda]ZVOJGCA at ACHKNPQQQQNLGB=9744=B=;<4)$"%+16996337=@=940////1343/+)'&%$%(*-03577640*%# !-56/%#+389865469=BFKQUVWXWVTRSUWWVTTTRPPPNIC<84/-.//+)))))))'%" "#" #&())(('''&$" !#"""""""" !"##&*157522573+"Z=AOGE=$888:=<73331///00//.,+*))+,,,,,,*('()*+,,*))'&%$#$$$$$$$$%$&'""3IVWUSPMKJHFEGLT\chigc^YUNB==<>?BDGHHIKMPQOLHB>:88<DHD@<4*%# %,2:==;88=@?;72.---.0121-*(('&&&()))*.38:<:3,& +23,#!(046653358<AEIOSTVWWVUSSTUUTSTVVTTTQKC;62/--.-+)))))))&$! #%)-//001110.*&#! !#$$$$$$# "%'+/2577521354/&PQLLRMEB;:?A?<:975422233220/-+**,------,*))**++*('&&%$##$$$$$$$$%$&'""3HTUVWXYZZXTPMOU[bijgb\UOJDCEGJMPPMIGFGJMPPMHC>;88:@CC?91*%$ !&,3;>><:;?C@<83/..../00.,)''''''(('##(-37;;71( "+12+#%,13431247
;@DHLPRTVWWUTSSSSRQSWXWWWSKB941.,++*)(((((('%" "%)+/47789;;<:73.)$! "######" #(,18:987420.030)" @RH9=4-;ABFD@<>?;87555666531/-++-.......,,+++**)&%$$$###$$$$$$$$%$&'""3IVYYZZ[[\YUPMNT\djkgb[SMIIJMORTVURNKIHJLOONID?;96338=;4-*'$!"'-49<=;9:?DD@<732210///-+*)'((((''%!!#&*.1451( %-22,$#).13210259>BFILORUVWVUSRQPOORVXWXWRI?51/-+)(('''''''&#!!"%'*-1458=?@ABCDDA?;60*%" $*06=>=;841.-1661+'&$# SXG;FG;=CFGEB at AA=;:8888998641/--.////////.-,+*)($""""""##$$$$$$$%$&'""3K[^[WSPMLIFBAFP[ellhb[SMJIJKLLJIJMNMLLMNPPNJE@<:5-)/990*+(%" "(.38;;:8:?EFD?:7555310/-,+*(()))'%$#"""#%(+.,& !&-11+$#(-0320/148=ADFIMQTVWVUSQNMMMPSUUVUNE;1.-+)'&%&&&&&&&%!!%*059=@BCDFGGHHHIHEC@<70+&! $+28<>>=94/,.4:<9654/+'"NJB<BNK@?CDFGEB@>=<:::;;;:8630...//////000/-+*(&#!!!!""##$$$$$$$%$&'""3K]_[UOIEEDB?>DP\fllic\UOLLLKIE?:;AGJMOQQRQOKE@=;7.)/;;0*,)&"!#(/49;<;9;AFHE@;86665310.--,))*+*'%%%%#!!"$&'%# %+
/.(!#(-143/.037<@BEGKOSVWWVSPMKKLNPQRSQJ?6.-,+)&$$%&&&&&&$ !%*2=DHLNOONMMMLLKKIFDCA<72,$!!!!!!""! $+38;=??;5-)+06999;<:5.& IJME;BIA=>AFJHC??A?>>>>>>=:841/./000000111/-*(&#" !!""$$$$$$$$%%&%%%6N[^[WRNKKNNKJMV_flkgc\VRPSTRNHA;9;AGLQTUUROKE@<960,2=<1+,*'$#&,28:;;;=@EHIE?:77776520/..-)()*)'%%''$#"#$%$#" "&)(#"',043.,/26;?ACFJOSUVVTQOMLLNNNNOPNF90++*)&$""$&&%%%%#"(/7EMQTUVUTRQPONMMKGEEC?;72)%$####$#! !%,267:==;5-%%(-0137;=:3*#IIKF>@DA>?CGJIFEFGGFFFGGEDA=:6433332222321.,'$"! ! !"##########&$!)CTX^`_]YVRTVXWXZ]aehgd_[WUWXZXTPJECAEJPTWXXSOJD?;83228;70--+('(+29==;:>FLNNJE=87787752/-,-+'''''&%&&'&%%$%&'&#! "%),/.+*-159=?@CHMPSSPONMNOPQQONNNKA4+((&$#!!"$$$$$##!$.7ALQTVXXWWVTSRPONMIHFDB?<80,)&$$$$!!(-102698991'#%&')-149::4+"JHFCBABBACGKMMLLNOOOOOONMKIEA><:7765432211.+'#! !! !"########"#%# ,EV[bdcb`]ZZ[]_`abcefea]ZXWXZ[ZYVSPNLNRVY[\[UPJD?<;;<=>:40//,)*,06;@B@>DOVWSKC;6688753
1.,++*&%%%%%%%&&&&&&&')(%!!"""$%()+*('+/48;<>@EIMOONMLNOQRSSPOOOKA3*&'%"! !$$$##""!"*4?HORUWXYXXVUUSRQPNLIHEB@>;4/+'$$%$!!(-/.17:8;>6+%%$$%(+-1:C at 4' IGDA@@BCDGLQTUUVWXXXXXXWUSQNJGEC><:8531100.+(%#"""! !"########""#"!,AS\cffffdbbcddddddeec`\ZYZZYZ[\[ZYXWY[]___]WQJC@@BFJJE<3022-+.0369;;75;FMNLGA:6677631/,*)((%$$$$$$%%&&&&&&')(&#! "%())((''&$%(-26:;;=AEHKLLMMNOQRSSQQQQMC5+&&$"! !"$$$##""!""%*3>HOTVXZ\\\[XWVUSRQOMKIFCA?<61-(%%%%"!',.,-488;>7+%%###$%%-?RSC1'$ HEA>>?ACGKPV[]]]^^^^^^^]ZXVSPNLIEB?<7410//.+)'%%$$#!!!"########"""!"*<O[bdfghhgfggffedcddc^[YY\[ZZ\_`aa```aaa_^\XQJCADILNLG>6122.-0355663/-3>EFEC at 9678752/-*(''&$######$$%%&&''(((&$#"! #'-.,*'%#!!"&+059:9:=@DGIKMNOOPQRRRRSSOD6+&$#! !"$$$##""!!$)0:ENTWY\^_`_^ZXWVTSRQNLJHEB@=83/*'%&%#!&*+('-348;3'#$#!! )B]bP;0+"FC?;;=AEINTZ_abb```````_[YWUSPNLJGD?:620/.-,*)'''&$""""##########""$)6IY`adfghhghhgfdcbdec^YXY\\[[^adffebaaa_]ZXVQJDCFLLH
ED?8200..022214986<FNOKE?:89:851.,)'&&&$$$$$$$$$$%&&'(('''&%#" !%)./-)&#! $*/59:::<?BFIKNOOPPQQQRRSSOD6+$#! !"$$$##"" !$+4>HPUY\^`bbb_\ZYWVUTRPNLIFDB@:61,(&&&$! %()&&-46:<3&"#"! !:W^O<3.#EA<99<AFKOU[_bcba``````_[YXVSQPOLJFB=841/--,+**))'%#""""#######%%##&'/BU_`ceggghhhggeedege^YVX[]]^`cefgea``_]ZWVSPKFEHLIB?@<60.///..---2:;9?JQRMF@<;<=;72/,*('&&&&&&&&&%$#$%'()('''('%#!#&*,,*'$" $*06:<<<=?CGKNOPPPPPPPQQQQMC5*"! !#$$$##""!!%.8BKPTZ]_abcca][ZYWVUTQOMJHECA<83-)'''%" $'&&*4;=AB7)!"""!+CKB62.#D@;77;AFLPUZ^``aabbbbbb`]ZYWUSRQNLHD?;73/--,,,,,*)&$#"""#######%(%$'&);S`bdfhhhhjjjjiihjkg_XUVZ]_acdeedca`_^\YVUROLIGHIHCA=6/,-01/,)'()/5549DLLJEA>>?@=930.+)('()))))))'$#$%'())&&()('$" $()('&$#! !%+27<>??@AEJNQQQPPPPPPOOOOKA3(! !#$$$##""!$)3>GNRUY\_abcba^\[ZYWVURPNLIFEB>:4/*(''&" #%%%-8?ACC8(!"##!#3:9664#D?;77;AFMQVY^__abcccccca]ZYXVUTRNLIE@<95/-,,,,,-+)'%$#######"#$'*'&(%&8P`cfhjjjjmnnnlkkl
lg_YUW[^bbddedcca``_\ZWUQNLIGFGGHC:1--1440+%$%'.566<EKLJEB at ABBA=610-+*)**++,,,,*'&&')))(&%&(('%"#'(&$#!! !! "&,28<?@ABCGKPRRQQPPOONOPRSOC1% !"#$$##"##(.8BKORTX[]^```_]\[ZXXWURNNNKGEF@;5/*''(&# !##$,6<=?>3$ "$$" #09==><#B>966;@GMRVZ]_`aaccbbaa^\ZYWVTSQNJIFA=95/-,+++,,**)'%$#$$$"!"$&+,)()&&6M^ceiklmmnpqnieddea[UTVZ_bddeededaa`^\ZXVQNKIFEDFG at 50168950)#!$(-259?FJKHECBBCDC?853210/.-.1234431000.-+)'&%&((&" "$$" !!!"',17;=??ADHKNPRQQONMLLKNSXVI5&!! !"%$"!#',3;DKOPRVXYZ[\\[[ZZYXWVUQLMQNEEHC>80*'''%$" !%,6:8:;0##%%#$1=DEB9'>:746:@GNSWZ]_`aaaa`_^]\ZYXWUTSQMJIFB=950.,+**+,+*)('%$$%$"!"$'+.+))''5K]behkmmnnoojb[XYZWRNMPT[adeeeefdb`_][YXUQNKHFDDFF>305:;95/("!$)-26<BGIIGDBCCCCCA;9876544347:<<=<<;;962/-,)&'))'"!!! """#',27;=>?ADGJLOPPPONMKIEEKRSK<."!!"%$"!$(/4=EKNOQUWXY[\]\[ZYXXWWWTOOSODBFE@;3,(('%$$ !'/7:9:<3%!$&%!#1?FEA7) 85214:AHOTW[]_`abba_^\[ZYYXWUTSQNKIFB>951.,+**+,++*)'&%
%%$#""%(,.+**''5J[adgjllmmnmg]URRROJFEHMU`eeeeeeda_^\ZXWUPNKHFEEGF>3/39:71,%!!%+/37=CGHHFCBBAAAA@>==<<<;;<=@DFGHHHHFC?;752.++,+(#!$$"$(-27;=??ADFIKMNOOONLJFA>?BDB=5( "%$"!$)/6>FLPPQTUWXZ\]]\ZZYYXXYXTQSOGDFEA<61,)'%%$!!'1:=;=>5(!#%&%"'2=CD at 8) 31/04;CJQUX[]^_`ccb`^\[ZYYXWUTSQNLJGC>:61.,+**+,,++)('&&&%#"#%(,.++,('3HY_bfijkklnmh`YVVTPKGFIMUaffeeddc`^][YWUTPMKIGGGIF=2.2774.(" %,048?EHHFC@???????@@@AAABCEHKNQSSSTSQNID@=840./-)$ "$%%#$(-38<>@@BCEGHJKMMMKHEB?;633464-% "%$"!$)07?GNQRRRTUWY[\][ZZYYXXXXSONMIFEA=8530-)&&%!"(1:=;=>5' "$%$#$*2:BEEA9* 31016>FLSVX[]^^`bdba_^][ZYXWUTSRNMKHD?;71.,+**+,-,+*)''''&$#$&)-.,,-)'2FX^adgijjknpmhdcc^YTOORV\dgfeedcb^][YWUTRPMLJHHIJF<1-0551+& $+059 at FIGC?<;<==>>@BDDEGHHJORUXZ[\\[ZXUPKGC>9410.)# !#%&'&$%).49=?ABBCDEFGHJKJGC>:62,'&+482*!"%$"!$)29AIORSTVXY[\^_^ZYXXWVVVUPICBB><<:42330+'&&"#(08;9;<3% #&()-4<CHJGC9* 6435:BJPUWY[]]]^_`__^^
]\ZYXWUTSROMLIE@<71.,+**+---,+)(''('%$%'*-.,-.*'1DV\`cfghhjmqqnlmmic^ZY\`eghgfdcba][ZXVTSROMLJIIJKG<0+/330*%")/4:BHIFA;768:<>?BFIKLNPQTWZ\^_`_^][ZWSOKGB<731-'!!""$&()))'%&*/49=?BCCCCCCDFHIGB;4.'%"!)6=8.$"%$"!$*2:BJQTUVZ]]]^^_]YVVUTTSRPLB:<B=8E?51342-(''##(07;9;<3$"&)+.4;CJLIC9) ;:89>FNSVXZ[]]\[YXYZZ[[[ZYXWUTSRPNLIE@<81.,+**+,..-+*)((('&$%(*-.-./+'0CT[_befgghkopmlmonid`_bgjihgfdcb`\ZYWUSRQNMLKJJKLF</+-11.*% '-4;CIJF at 92147;>AEMQSUWZ[]^`abba`^ZYXVSOLID>830+% !#&'()+--,*'%&*/5:>ABCCCBBBBEGGD=4+$ %2;;1&"%$"!$*3;CLRUVVWWVVUUTTTSSRRQQMGD?<HYZVVM<3452,(('$ $)2:=;=>5("""#$&(''-:EJGA7) B?<;?FOUXYZZ[[ZXTRSSUWXYZZYWUSRPMKJHDA>:1.,,,++*--,+*))))(&&&(+..-.0,)0>QZ_abegfhkopnllmpmhdbeikjhgedba_[YWVTRQPNMLKKLMNE9-),/0.)%&,6=EJJE>71/25;?CIRVY[^abbbbccba_\YWVTQOLID>71-)$!"&+--.010.+(%&+05:>@DEBBABCDEEB>6-&""## !(062)!"%%##',5=ELQTTSMKJFEEEFMOPOONNI@=;AZx}qjX?6540*(('$!!%)5=@@A at 8.&%##"#$!#3BHD=6)!
NIC>?ENTWWWWVUTRNLKLNQUWXXVTPNLIGDDBA?>91--.//+)*+++**))*)('(*,---./..08IX`__cghilmmkhfhhgb^^aeggfedb`_]YWVTRQPPOMJJKMOLA4)%)..+(#'19 at FKIC;40/049 at GMTX[^`bccdcdcb`^[XVURPMKHA;4.)&%$ ")/334543/+'$&*06:=ADDCAABEFB@<60*&$"##" !%-/,&"%%%'+29 at GKLLNJGFB;:@BAFKNONLLH?;5;\o448785/*))'%##$*3;?@@=7.$""!!! 2DG?:5+#WRJEDGMQTTSRPONLIGGGJNRUVTQNJHFDB@@?>>=:3//132-))********))()+,---.//015DWa_^dhiklie_YUSRPMLNTY_dedca`_]XVUTRQPQQNJHKORN?0&#(-.+&#)3<AGJHB:411139AHNUX[^`abbcccca_][XVTQOLJG@:3,'%%%# #*15656640,'$%+06:=?@BEFFDB?<;:72,'$"#""! !%)+' "%&&(.5>DHHFDEHIJC;@KNHGJORROMJE at 42Lnq[4137:94.)(&$###'-38::50*" "3DG>:8-$[XSOMMOPPPONLKJHECCDGLPSRPKFCAAA??>==<<:5224751,+++++++++*))*+-.--.//015CVba`fjjjhb\UPMKHGDDFJPWaddba`_\XVUTRQPRRNFDGNRO;-$"'--*&# !,6>BGJHA942225:BJPUX[^`aaabbbb`^\ZWUSPNKIF@:3,'%%%# $*14556640-(%&+17;>>=AGLKD<6479:70)$##""! !#%$!!""#&&&(-5?EHHFFHR]\OGP^_SJKQVWSNH?:.$0HN at 414:>?:3+(&#
"!"$+05873.(" "1AD>=>-$WWWVUTRRPPOMLKJGB@@AEINQRNHB>>@@?==<<;;:7668:94/,,,,,,,,++***,...-.//014ATaaagkjgd_[YYZ[XURONPRX`dcb`_^[XVUTRQPRQI><AINJ6)!!',,)%# #/9 at DGIF@953336<CKQVY\^``````a`_][XVTROLJHE@:3,'%%%# !$%%" %*03445641-)&',27<>>>BHKIC:5367750+'$#""! !$&&&'-4>EHIHJOYa[IAK[ZMGIOVYULC;92()6:667:>BB=5-(&#! $,38;;72+#".=B>@D,$PRUXYXWUTTSRPONJDA at ADIMRTQIA>?BC@==<<;;:988:<;60-,,,,,,,,++++-//.-.//012>P_aagkifdb__adda^\ZYZ[^bcba_^][XVUTRQPQLB64;DGA1%&,+(%# &2<CEGHE?954558=ELRXZ\^``______^[YWTRPNKHFD?:3,'%%%# #'+-,(#"&+02335642.*''-38<?@CEFGEA=;9962/.,*%#""! %''&',3>DGGEEGKH>.(5GHAAFKSWTJA=CE@>@@?@ABDEB<4-*'$"! $,38<<94-" ".<A>AF+$MPTXZZYYXXXVUTSOIEDDFJMSXTJB>AFGB?>==<<;:99;=<71.--------,,+,.//.-.//0119L\_`fihhgeb`__]YWWY[^`bcba`_]][WVUTRQPOH;0/9AA:+ %+*'#"! (5?EFHGD>856669?FNSY[]___^^]^^^\ZXUSQOLJGEC?:3,'%%%# $*032,% #'+/1224552/+'(-39=@BFGFDCBBBA=71,**(%#""! !%''%&+2=CGFA<:95/&
#1DJEEEHOUTJ@<BHJIGEEIJIIID;4/-)&$"!#(.37850)! #/=A=?C,$SUWZ[[ZZ[[ZYXVVSOKJIILOUZVKA>AHJD@@?>>=<;99;=<72........--,,-.00.-.//01/6GX\_dgfhhgeb_\YXXY[]_abbba`^]\ZWVUTRQPNF9.0;B?5'%+*&#"!"*8BGGHFC=86678:@GOUZ\^___^]\]]][YWTRPNKIFDB?:3,'%%%# %+264-$ $(,/01245530,().4:>@CEGGGGGFEB@<6/)$""#""! &*(&$&('%&*/7?GJGB>=<=96>MSPLHGMUVMD==@EGFDHLNMMLG>71/,)&$#$&*0452.( %1 at B<<>-$Z[\]]][\]]\[ZXWUTROLLOQVZUKA>BHJFBBA@??=;99;<:63//////...---./0/-,.//0104CU]^`dffgghgdaabcccba`aaa`^]\[YWVTSQPOMD6,1?F?2#%)(%"!#-;EIHGEC>:7578<BJRWZ\]^]][[[[[[YWVTOMKIGECB>:3,'&&'# $*141*"!%),./0245530,()/6<@CCDEHJJIHECCA;2' #""! $+0/+'(*'%&+03;FMOOONHIFACKPPPLINVXRJDBCFIIIKMMLMMHA;74/*&$#$)-37973-! %2?B=;:-#_`abb`````_][YXYXVSQQSVYXSKDABFHHFDBA@>=;;;;;96421100//...////..--./12323<L[^[_ffeghhihhiiigeca__^^\ZYXWUTSQOLKIA2)0DKA- $%&$!$1 at HJGEDDC?:669>EMTY[[[ZYWVVUUWWWUSOJFFECBA@=82,)(*($""! #*/0,$!&),--024541.+(+3:ADEEDEGIIIIIGFD<0% #
""! #'+--*)*,)$%,47;CJPTWTOLKIJNQVVRMPX[ULGFGJLLMLMMNNLHCB?;3*$!!$*059;:80#".:??=9." `acdedcccca_][ZZYWUSSVZ[YTMFCCFHHGECA@>=;<<<:864322100/...0000.../01234454 at T`__deefgiklljjjigdb`]\\ZXWVUTSRPMKJH>0(3GNB.!#$$!'6CJJGDEGGD?99<AHOUY[[YWUSQOOQTVVURMFBBA@@?>:63/,+,+&$#" $*.-(""'*,,-135541.+)-5<BDEDEEFGGHIIIIF=0%! "$'))'%$(,.*%&.7<?DINSVVRONOPTWZ[VQSZ\VNIILNOPQQPQRQOLHEB<3)""(.379970$'2;@B>/!!bceggggffedb`^]\YWVUVY\^\WOHEEGIHGECA@>=;<<<:86521100//.-.0000..12233345517K]b__bdfhjmoolkkjhec`\ZZXWVUTSRQOMKJF<0-9JOC0#!$%!,:DIIGEGKLKF@?BEJOTXYYWTQNKIHLRWYVQJC@@?>>=;85420/.,)&# "$(,+&!"&*,-.246652.,,07=BCBBDEFGGHIIJJH at 3(! %)**($ &,.,')19?CGLPTUWXXXXY[^_\XUX]_ZRKJKMOPQQQQRRPLHFA;1' $)/3542,$ !&,4;@C at 0!!efhjkkkkjigfdb`^ZXWWX[]_^YQJFFGIHGECA@>=;<<<:8642100/...-.0000..1222222356;GTZ[\^adgjmonljjigdb^ZWWVUTTSQQPNMKJE:23>LNB3'" $&"#1?GIHGFINQPMHGHJMPTUVUROKGEBCIRZ[WPIA?>>=<<:5455420/,(#!"$')($ "&),.04
67752.,-28>AA at ACEFGGHIIJLKC7+$"!!! %())'#$+/.*+3<BFJOSUVY]````ab_ZVW[ac`XNJIIHIJKLMONLIEC?:0&#(-1331,# !!!!&8===>@B>0!!giknopponmkigfda\ZZZ[\]^]XPJFFHIIGECA@>=;<<<:864100/..---.0000../00112237 at GIJOVZ\^`cfikkhgfeca^[VTTTSSRRPONMLKJE;47 at II@4+&"!%&"&7DIIHFFJPTTQOMMNPRUUTROKHDA at CKU]_ZRJC@@??>>;76676420.*% !""%'%! !!#&)-02678862.,.39>AA?@CEFGGHIIKNNG<0'%$%$##""!"#&''%"!$*00./6=DHMSWXXZ`ccccba]VTX^dfd^UOLHFFFHKNOOMJFC@:0&$).2442,$!#$&(*.CEC@?@A=0!!jlnqsttsrpomkihe_]]]]]\\YTNHEFIKIGECA@>=;<<<:8641//..--,-.0000.../023567=IPJGMVZYY[]`bddba`_][XURQQQQQQPONMLLKJE<8:@DB;4.+(%$$%&")<JLIGFFJPTTSRRRRSUWWURPMJGEDIQZab]VNGDDCCBB@;9865321/+'# !#$#!""#%)-1479:962.,.38>AA@@CEFGGHIILOPK at 3+'&&&%$$#" #&'&$"$*12029?DHOVZ[[\^aaa`^[WTU[addb_YTPLIIILQSTTROKGB;1' $)/3552.&$&')+-/4779<?B?0!!lnqtvwwvusrpnljhb```^\ZXUPJFDFJLIGECA@>=;<<<:8640/..-,,,-.0000../1369;=?DMNHJW]YVUVWY[\\ZZZYWTRPOOOPPPPONMLLKKJF>;<>=;730.-+)(&&", at NNIGFFJOSSRTUTUVXZZYWUSQOMMRY`eeaZSKIIHGGFE
A=953231.+)&# "#!"###%(-259:;:72.+-18>ABAADEFGGHIJLPRNC6-)%%%$##"! #&&%#!#)2434;@CGPX]_^][\\\ZWTSU[`cb^[XUQMJIKNPSTUUSOKHC<3)"!$(.2431.*))(((('&(,29?C at 0!!lnquwyyywuusqnmjedcb`^\ZTNGCCFKLJHEC@?<;::::97640...-,,,-.0///..589=?BEGKNHAOefWTSSTVWUTUUUTRPONNNOOOOPOMMMJKMKE==?;87640...//,+#/DONJGEDGLQSUUWVWWX\]\[ZZXWVVY^bfea\WNKKKKKJIE@:42232.,*(%! "%$$%).48:;;:72.+,18>BCCDFGGHHIJKOSUPF9.(###"!"!! "%'&$" (1447>@CGOV]``^\\\[YURRW\_c]TOLIEDCEHMOQQRRPLHFB;2,&"!"&),/0/.,*('&$#"! #*2;@C at 0!! kmqtwz{zyyxvtromjhfdba`^VNGCCHKLJHFB?;9767776653/.///.--,../0238=ABDGJMNNQD7Knp\TSQRUVSQRRPOONOONONNNNNLLONILRN?:?B:48:5/+*.4895+"$5GNMKGC@@EMUYXXYXVWZ\\\^^_^]^_`cdda]WOLJKNONLHB:53331.--+)%!!%('%&)/6;<=;962.+,19>BDFJJJIGGIKOSWXSJ=1(# !"$" "&'$"! "+224<CCCEKRX]`cbb`^\YWYYXQEABDBA>>>AEJMOPQPNJFD>7331(#%')*))(&##"! )4>DE>0! jlptwz{{{{zywtqoljhedccaZQJFHKNMKHEB>:755555555410111/.-+,.048;?CEFHJMOONQB1DlweXSNOSVVSRQPNNNOPOONNMMLLMPMINTN=7 at C:5:<70+)-6=@=5*,<JMLLGB=;?JV
[ZZ[XUUX[\]_aaa``abdeda^XPKJLPQOMHB;76520000.,)&#"&('%%*18<>=<962.,,2:?ABEIKKHFFHKOTXWSLB8/$ !%)(#"%# $+5846AIHEEIOUZ^bddca_]\[ZVPJGFHHFDBABEHKMNOOMIEA<67>=0%$%'&$#! (5AGF?1! jlptwz{{|||{yvtrnljgedcb[TNKMOPNJHEA=965555555554433210.,-16;AEGFFGIKMOOMN?,:b{ueYRORVYYURQOOOOPOONMMLKMOQOOUWJ:7?B<9;<83/+-3<AD?67CMMKLHB:6:ESZ]]]ZVTW[]_acccbbbceeda]XQLLNRSPLGA<9850.0221/,*&! $'('%%*19=?><:73/-.4;?@@CFIHFDDFHMRTSPLGC;.&" $)*'%$ #-<EB88DONGEINSX\_aaa`_^^^\ZXUSSSSSPMJIJLLKKLLJGC?:6:CB3%!!"! (5AGG at 1! jlptwz{||}}}{yvtrolhfddc\UOLNOOMJGD@<8654555555554210000148=BGIIHGIKMNNNKI;)0Ty
wkaYUVXYVTRPOOOPOONNMLKMPSV\`XC57?A@>=;940,+08 at FHAAJPLIKHA714@NX_``\WVX[^abdeddbaabb`]YUPLMPTTQKE@<:84-*,///.,*'"!%'(&$%*2:??>=;730./5<@@@AEGFDBBDFJMNLKJJJF<3*"#&&%"",:KSJ<9EQQHDHLPUX[]^^^^^_```_][YXXWVRONNONIHIIHEA>924;:-" )6BHGA1! jlptwz{|}~~|zwtqnjgeed^WOKKLLKHFD@<85445555555320//125;?BEGHHGGIKMONNMKE7')Elwj`ZXXWVTQPOOOOOOOOOOPTX`heS
:/9>@CC?;940-+-4>GKHGNPJGJG?4-0;IT^aa]XWY\^abdedda^]^^[XTPMKMQTTOIC>:750)&&)*++)(&# #&((%$%*2;@@?><840.17>AAACEGFCBBCFGHGFFGJLMJB6)! "!&3DU[RB=FQPHDGJNQTVYZZ[[\\_bca^[WUSPNKHGHJIFEGHGDA?8.(*)! !*7CIHA1! jlptwz{|~~|zwsplifefe]QIGHIIGFC?;744455555553200148=DIKLKHECFJMOPOMMIA3)'5Vv|oc\ZYWURPOOONNOQRSTVZ^fi[B0/==>FHA;8421005>FKHIOOHFID<3,.7CNX]]ZVUW[]_acccb`\[\[XTOLJIKPSRMGA;51/+%!"$%'''&%#" !$()'$#%*3<@A@?<951/28?CDEGIHFDBBDFGFEDEGJLPQLA5,'&&&$!!+:IZaYJDJQNFCFHKNPRUVWWWXX[^^ZVRPOLHD@=<<=?BDFGGDA@:, ! !+8CIIB1! jlptwz{|}xurmjgfjleUJFHJJHEB>:6434555555654336;AEKNOOMHCBFKNQQPMMI=1,')?^}ofa[YVSQOONNNPSVX[^bde^F,&4?<=ILC;9679869 at GIEGNLEEHB:2-.5>GPTUSPOSW[]_aaa`_\\\[XTOKFFINRPJE at 91+(%"!$%''&&$#"!#&))'$#%+3<AB@?=952039AFGILMKGECCEGHGFHIKLMOPNHB>;::863008EQ^eaUNQSMECEGILMOSTTSSSSUUSOJHHJKJFA<8669 at DGHGEBB=.!"!"+8DJIB2! lmqtwy{|~zwsokhfiogXLGHIJEBA=9522345665446779=BGJNNNNLHDCHLORRPLLH:00,
&2Hn~|rj`ZVSRPNKLNQUY]`deb^P0$8C?@JLC;88<A@<<AFFDGLKEFGA:4015;AJMNLKKORXZ\^_`_^___^\XTPJHJMPNID=6-&#" #')*)'%&'%%&(+*'$$&,4<ABA@>;73139AGJKNOLIGFFGIJIIKLMMMMNNKJIJKLKIFDCHPW^dcZVYYQIFEFGJMOQRRQPPONJFDBCGJONLGC?<;<BEGHHFBB;/$""! "+8DJJD2" oqruwyz|}{yvrnjgghbYOIFFC@??;6111455555568:>AEIKMMLKJHFEGJOQRQOLKF94:;0,6Pf~ylbYUUTQNOQW]cgknk_F- +;CCGLKB:57?GGA<?DFFHLKHFD@;9767:?EHHHHJLPSVY[]]^__``a`^ZXQNKJKJFB:2'! #(.21.''*,---,,*&$$',5=ACCA?=96337?FKMNNLKKJJKKLLLKKKLLNOOMLMNQQRQQOPQTV\`_Z\bb[PMHDEHLPQQRQPNLGB at ADGLQQOMLJHFDFEGGHIFA:4+$"! +8DKKB3"rstvwyz|~}|zwsokhfd`YRKFDCBA>81/16;:6336:=?ADHKMMNLKIGFFGILPQRQNKJF=<HK=-'0Jjzmc\ZYXVW[bjqux|yfE)#2=CFKLJC;57 at IIB<>CFHJLKIFC?=;:99:=BDEFIKNPRUWZ[\\]]^^``_\WRMHFGFC?7.% $+2761)(,0111/.+&%%(-5=ACCBA>:7447?FKMMLLLLLLLLLMLKJJKLNPOMLLMOQPPQQRSSUY][W\ef^VPJEDGLPRSSSRPNKHGJNRUXXVSQOMKIIIHGGGD>80*" *8DKKD3#uuvxyz{}~|{zwsokhhfc\UNHDCCC?968?FGB93
39BGHIKMOOONLJIHGHHJNPQRPMJHE at DT]P9'(ChqaSMNU`how{}}kD' (6>DHLNKD<79 at HIC>?BFIKLKIFC?=;:99:<>@CFJMPRSUWYZZZZYYZ]`^XQIEBACB?;4,$ %-49:5.+.23321/,'%%(-5=ADDCA>;8558?FKMLLMMMMMMMMMLJJJJLNOONMMNOPOOPQQRSSVYWRV__YURKECFKPSUVVVTSRSTVWY[\]]ZUPLJJKKIGFEA:51+" *8DKKD3#xxyz{||}~}|zyvsoliige_XPJEA at BDEGLTWPG@::@GLNNOPPONMJIIHHIKMNPQQOLHEB>CUc^I2/Jp
~k[TZgw
z{s\9$$0:?EIMOLE=9:AGHD@@BGJKLKHEB?=;:99:;;>AFJNPRSTVXYXXWWVW\`^UJB><=?>;6/(" &.6<=82/0233310,'%%(-5=ADDDB?<9669 at FKLKKLMMMMMMMLKJIIJKMNONNNNOOOOOPQQRRQSPLOXWTUSLECEJNSUVWXWVVYZZZYYYZYVPJG=521,# "! *8DKKD3#{|||}}~~~~|{yxvsoljihfa[TMHDDIRWYZ][QJHFFHJLNNOONMKJIIHHJKMOOPQQOKGC?<<EQTF10Jq
{ss|zof`SA+#*6=@EKOQNG?;<AGHFCACGKLLKGDA?=;:99:;;=BGKMNOQRTVWXWWVTV]c`TG=;9;=<72*% &-6=?;51122320/,'%%(-5=BDEDC@=:77:@FJKKJJKKKKKKKKJIHHIJLMNOOOONNNNOOPQQQQTRMQZZWWUMFCDHLPRTVXXWWXXVTRQOOMJEBBDHJKHEC@:200-$!" *8DKKD3#~~
}{zxwurpmkjgfb^XQLIMU]`]YVRMKMOOMKKLNNNMLJHHHHIKMPQPPQPNIEB>=736:4).Gj~zvuxzvqi_SG=94,$$-8>BGLPROH@<>BFHHEBBHLMLJGCA>=;:99:;=@DHJKJJLOQTWXXXXVXaieVG=;:<=;5.'! $,5=?<7200110.-*'%%(-5=BEFECA=:87;AGJKJIHIIIIIIIJJHGGHJKLNOPPONMMMNOOPPRUYWTYcc^[WNFBCFILNPSUVVUTSQNKIGECA@@ADHJIFB@>90-.,&###! *8DKKD3#~~~}{zxwurpmljfdc`[UPNQWZZUPNNMNOPPONMNNOOOMLJGGHILORRQQQPMID?=?:.(-,(.<Pfv{gcfkonibYRI>3+%&))'(-6?EIMQSPIB>?BEHIGCBHLMMJGC@>=;:99:<@CGIJGDDGKOSVXZ[ZX[eokYH?>=??;5,$ "*4<?=83.-...,+(&%%(-5=BFFFDA>;98;AGJKIHFFFFFFFGIIHGGHIJLNPQQPNMLMMNOOPQSWWT[egb]XOGBBEGGHKNQRSSSROLIFDCABCEGHJJFC@?=80,,+(''%! *8DKKD3#~~~}}|zyvutqpnljfdda]XSPOQQOMKMOOONNNOOONNOOONMKHHHJMPSSQQPOLHC?:>=1+01+,.3<FMMGAFQdt~zm\SI at 6.*+,,+),3?GLORTQKDAACEHJIFFJNMLIFB@>=<;::<>CFHIIGDCGKNQUXZ\[Z^hrlZJ?>?@>90)!!!"(09=<83,*+++*)'%#$'.6>BFFFEC?<:8;AFJJJIEEEEEEEGGGFFFGIJKLOQQPMLLMNNOPPPPRRPV_a^]YNGFFJFBBFKPRRRSSQOMKIHIJJKLLMKE?=CA;/+*))*+(
*8EKKE4# ~}}|{yyvtsqpnmljfedb^YURPONLJJLMNMMMMMONMLLMMLLLJIJLNPRRQPOLJFD?:=;1.10+,,,.011+0BX_pqcZSMA2*(*)(')2 at KPRTSPKFCBCFGJJJLMNMKHEC@>=<<=>?CEGHIIHGIJLLNPTXXYZ_hmfVE<<>>:2)"!!$&'%! !%*29;7/(&&''''%" &/9>ADFGFEB>:8:?DHKMLHGGGGGGFDDCCDFHHIJNPQPNMMNNONOPPOPPPTXZ[\XMFOa_SJCCEJNPQRSUUTSRSQRRQOMLKE:>OT?/+)((,0-% +9EKJD5$ ~}|{yxwvsqpomlkjgfeb^ZWTQPOMLMMMMLMMMMNLKKLMMLKJJKLMOQRRQPNKIFDA==9/,0.*+.01110/5HUXdy{nd^\ZM7(&'(&$'2ALSTTSPKGCCDFGJKMNONLJGECA?===>@BEFGGHIJJKLLJJLOSUUW\cd]NB;;==80'"#'*,,*'$!"&.575.&#$$%&&$!%0:?BDFHHGD@<89>CHKNMJHHHHHHGECCDEGIJJJLNOONNNNNNNMMNPQQRTWZ\[WKETm{tcTG??DHLRTVWWVUUUVWVSNIGC<F[[B/-)''-44.% +9FKJE6$ ~|{zxwvurponlkjigfec_[XURQONMMNNNMMMMMMLIJMOOMJIKLMNPQRRQPNKIFDB at A;.*./+,-./0113;HOTexvf[X[_V at .++*&#&2DPUUUSPJECBDFGJKMNONLIGDB@?>>>@BDEGGGHIJJKJIGEFJNPQRVYYRE=<>?=81*&(+.00.+(#"%+131+%"##$%%$ %0:?BFHJJIFB=99>CHKNMKIIIIIIIGFFGHJLNMLLKLMOPOONMLKJKNPPQUY^a_[PHSopXF?AFKPRTVWWVVUWYYUMEAC
FSc[?/.+''-6:70'$" +9FKJE6$ ~|{zxwvusponlkjihffec`\YWSQPNNNOONNNMMLLKIJMOOMJILNNOPQRRQPNKIFDCDF?0)-0.-----/03<EQg
bVUX\TA31/,&"%3FSWVUSOJEBBDFGJKMNNMKIFCB@>>>?ADFHGGGHIJJJIGB@@DHLMNPPMG>;>@?<71,)*-.00.-*'%&+01/)#!!"##$# %0:?BGIKKJGD>99>CHKNNKJJJJJJJIIIIKMOPPNKJJLOPPOMLJHGHLMMOSY_cc`WNQelYMFCCHLOSUWXWUUTRNHBBIR_eU8*,+(&,5;:50,(# +9FKJE6$ ~~~~~~~}{yxwvtsromlkjhggffeda^[XURQOOOPPOONMMLKJJJMNNMJKMOPPQQQRQPNKIFDDHLF5+.210/.--/15<CY
´¿sc`ZVJ8./0.($'4GSWUUSPKECBDFGJKMNNLKHECA@???ACFIIHGGHIJJJIE?;;>CGKLLJE@;<@A>:50-+++,--,+,+**,01/)" !""! %0:?BGIKKJGD>99>CHKNNKJJJJJJJKKJKLNQRQOLJJKNPOOMLJHGGIIHJNV]`^ZWRPYnufSA9?FJNRUVVSOKGDDEJR[c^H/$(+(&,5:9543.(# +9FKJE6$ }}}}}}}|yxwvtsrpmlkjhgfeffedb_\ZUSRPOOPQPPONLKJKKLKKKKLMPQQQQQQQQPNKIFDEJRN=1133210148=AFKb¿È¦ypaUD0'+/.*'*6HSTSSSPLHECDFGJKMNMLJGEB@??@@BEHKKIGGHIJJKIE>87:@FJLLGA>>ACA<62.-,*******,..+,./-'! !!%0:?BFHJJIFB=99>CHKNNLKKKKKKKKKKKLNQRPOMLKLLMOONMLKJIFDBCGOWY
TOPSRS_smTEBFHKLMMMJGC at BGNSY\ZM8'"&)((.8=:65642-($! +9FKJE6$ }}}}}}}|xwvusrqolkjigfedefeec`^[VTRQPPQQQPONLKJKMMJHHJMPQRRRRQQQQPNKIFDELWUE74542248?HPX_`g||sdYI7/10.,+.9HQQPRRQNJGDDFGJKMNLKIGDA@?@@ACFJMMIGGHIJJKJF=758>DKNMHA?CGE@:3.,+,,+****+./.*)++)% %0:?BDFHHGD@<89>CHKNNMLLLLLLLJJJJLNPPOOOONLKKLNNNNMMKD?<<@GPUTNNTTPUbou|zl\OKJIFB?>>?@DJQX[ZVK9)#%''&)3?DA956:==94.&#"! +9FKJE6$ }}}|}||{wutsrponkihggeddffeeca_\WTSRQQQRQPOMKJJLNMHDEIOTRRQQQPPPPONKIFEGN[_P=310/2;BMWblwskdZYcgmkgbWD at A70,*0<INONPQQPNKEDFHJKLMLKIFDA?>?ABDGJMMIGGHIJJKJF=769?EORPICCGKE>6/+++---,,,,-.,)'&''&# %09>ACDFFFC@=88<AFILMKJKJKKKKJJJKLMOONNOPOLIIKMNOOOPMC;88=ELSYSPTSNPTDGLVhmpj]TPJB:414;EOVZ\[TI=.%$&%$%,:FJF>78?DGEB;1-,+)('$ +8EKKG6$ |{{{zzzxusrqonmkhfffeeeffgfdca_\XVTSSRRQONLJIJKMLIGEGLRSQOOOOOOMLKLJGFIKRcmbJ5/.8DTbgmvtrxq\T`pvqss]H;-,7ELLMMOPQQQMGEGHJJKJJJIGDA>>?ADFIKLJGEFGHIJJHC>98;@KRSMGCBFF at 6.((*,,,,----,*'%%%%%#! &-5;=@@BCCB@;659=AEHHHGGHHIJ
JJJJKLMNNMMMMLKJJJKMNOPOJA957>FKNTSQRRPONE<71/Gi|ne^TI>639DPWWRLC<50+)(% #'4AIKHB=?CGJJIF?<;9753/((.8DJLG7${zzyxxwvsqponlkjfeeeeeeffgfdca`]YWVUTSRQOMJHHJLKGEHKMPQQONNNNNNMJJKIGGKOXiwpXB;BRev~||wlfos\H64AMPLLMNOQRSPIFGHIIJJJIIGDA>=?BEGJKKIFEFGHIIIEA=99<AHNMF@<;==6.&#$(+,+,....,)&%&&%$" !%+27:;<>?@@?;547;?BEGFFFGGGHHHHIJJKKLLLLKKKKJJJLNOONJA969AHKMOQQQQQQQNI?2.<VlvtlbXNGHPWXQE7.+*)(*--*&'.:EJJFCBCEHIIIHGEDB@><:757=EKLI:'yxxwvvutqpomlkjhfeeeeeefffedcba^ZXWVTSRQNLJHIJMJCBJPSRPNMNNNNNNMJJKIGHMS_o}ziZV\kz~zwvyjVFDOWUNLMNOQRSQLIGFFIKLJIHFD@=<?BEGJKKIFEFHHHGFB?;89;?CEB=73110,& #(*+,./00/.,*))(&#! $)/4668:;<<<8436:>ADFHHGGGGFFEFFGHHIJJKKKLLLKJJMOPOMIB;9<BHKMOQQQQQQSTRI<12<KWZWRMIEIXYN>.#"&&#$'*)'*1;EJKHDCDFHJJJJIIHFDBACFEBBGKLJ>* vuuttssqommkjihfeddddddeeeedcbb`[YXVUSRPNLJHIKNKDCIORRPNNNNNNNNLJIJHGIPWdr~xonqvyqpw
|jZOQ\b[RLMNOQRSROKGEEHLMJHGFC@<<>BEGJKKIEDGHHGEC?<:89;>@?;72.*('$! &+--/012210/-,+*'#
#(-14457899862148<@CFHHHGGFFEDDDEFFGHIJKKLLMLJKNQQOLHB>>?CGJLPQQQQQQSUVQE7.+-/013467;>=6,%#(,-)&&+/1148 at GKLJGDDGIJKJJKJIHFDCGMLFDGKML@,srrqqppolkjihfeecccccccdddddccca][ZWUSRPMKIHILOOJHHIKNQQONNNNNNLJIIGGKS\gr|}|}~rhjwsbVQYfj`SMMNOQRSSPMIFFHLMIGGEB?<<>BEGJKKIDDGIIFC@=;:9:<?@=;84/*&$"!"&-221234554310/.,($ #(-14567887630037;?BDGHGGGGGFEEEFGGHIJKKKLLLKJKORROJFCBCDDFILPQQQQQQRSUTMA4)$#$&(*,.,)()'&(.0.,/9GU^]URSTRNJGDEHJKKKKJJIHGFEGKHCCGKNMB/ pponnmmljihgfdccbbbbbbbccdddcccb_][XVSQOLJHHILORPMHEEJPRPNNNNNNLJIHFGLV`lsy
zkcj{oZPQ]lobSLMNOQRSSPNKIHIKKHGFDB>;;>BEGJKKHDDGIIEA>;;;;=?@A?>=:5-'$#$'-48754567765310/-*&" $)/479;;:9752..159=@CDEFGGHIIHHHIJJKLMMMLKJJHILPSSOIDCEGGEEGKPQQQQQQQQSUSK?3,)))(''&&&)--)''''+8Ng~qlgaYQKGEFHJLLLLKKJIIHGHFC at BGLNME4'&& nnmllkkjhhgedcbabbbbbbbbcccddddc`^\YVSQOLIHHIMPSTPJFEHLOONNNNNNMIHHFGMXeqvx}
}l^\h|||
|jWOSbqq`PKMNOQRSRONMLKJJIGFEDA>;;>BEGJKKHDDHJIE@<;<<>?ABBAAA?9
1)%$&*19<:75688886410/.+(%"!%+27;@A@>;841--048<?ABCDFHJKLLLLMNNOPPPOMKIGFHLQTTOHDCGKJFEGKPQQQQQQQRTVWSJ?5-*))(('(,031,'%%(-<Qj~rkf`YTPLGGIKLMMMMNNMMMLJEAADILLLI<121)" kjjiihhhfffdccbbaabbbbbbccddeeeda_]ZWTQPKIIIKNQSSQOLJHGHJLNOONMKIIGFHO\iwz{~
{q`RRcytpx~qbROWgtq^NMPOOPQSSOMLKKJJIGGEB@=::>CEHKKIECDGIHD?=;<>@BDEDCDDB<4+&%',39<:7679::975200/-*'$ !'/6;?DECA=951.-/27<?@@ADGKNOOOOOPQQSSSRPLIGFGHMRTSNIFBEJKHFGKPQQRRRRSTUWXVQJA/('-6598322/,,/1-0;HWdkc^ZXVTUTRKHIJLLMMPPPPOOOMFCCGLMLLKB::92,)"!" fedccdeeddcccbba```aabbccdegggfeca^[WTROJIJLMPRRQRTSPJDAEHLOOMIHJIHGITap|~
pi\NOaw~snszwhWNPZhql]RMOMLLNPOJHGGGIJLJGD@<::<?BFIKIDBBDFEDA?==>ACEFFEDFKKE;1+(+049:97679;;97422320,($")3;?ADECA>952.++/6<?@@AEKORRRRRQPQSUVTSQLGDEHJMRROMLHAAFIIIIKOQRRRSTUUVVWWVSL:..<RhcXJD=40/1/-2<DLWhyYTQNNPSRNKJIIKLNPQPPONNLHEEHLOMKID@>=:84,-1.%dcbaabcccbbbbbba`_``abbbcdfhhhgfda_\XUSPKJLMOQRRQRTTQJDACHLOOKGFIJIHLWes}}le\PSfzyuwyscUPS[djf[OGFGHIHHGCBCDFIKMKHC>
;99;>AEIJFA?CEFDC@>=>?BDFGGECISWRG<3./37999778:<<:8633442.*& !)4<@ADECA>:63/+*-4;??@BGMRTTTTTRQQSUVTSQLFDFIKNRQNLMLFCEGHHIJOQRSSTUUVVVVVVVRG>ATpymcUF90+)-5?GMWekbXRLJKNPNLJHHJLNPPOONMMLJFDFKNOLGD@=<<=<;?DA6)!cba``abbbaaaaaa`___``abbcdfhhhgfec`]ZVTQNLMNPQQRQQQPNJGFIKMNMJFFIKKKOZhu~yh`WPZp}{{yn]QMOQUWSLDACFHGC><=?BFHJKKKHC>:999;>DGGD?@DGFDB?==?ACEGGFCDN_hdWI?669;<;9879<==<96556640,(" !(3;@BDECA>:63/+*-4:>>ADINQRSTUVTSSSUTSRQMGDFIKNRQNLMOMKIFEFGJOQRSSTUUVVVVVVVTPPYj~{paP at 3-/5=ENXdhcZQIFGKNOMKIIKMOPPOONMMNMIDDHLNMHC@=<<>@ELRPE6)!a`_^^_`a````````^^^_``aacdfhhhggedb^[XUSOOOOPPPQQPNLKKKLLMMLJHFFILMOS^lx
sd[RO^v~wk[QMOQRPJB at DHHGD@;;?DGKLKIIIGB=:8888<CFDA>@FHFC@>=>ADEFGFECFVlxraQE=<>??<988:=??=:8667863/+$! &1:@BDECA>:63/+),39<=@EKNOOPRUVUTSSSRRRRNHEEGKNRQNLMQURLFCDGKOQRSSTUUVVVVVVVUTYcnw{||~|vk]QE835=JZhkaVNGEGLOPNKJJKNOPPOONMMONJDBFKONGB@=<=?AGNTSI8&`_^]]^___^^^^^^^]]^^_``abdfhhhgggfc`]YWURQQQPPOPONLKKLNOPNLJHGGHJMPRXcq{zm`YPM]u}
~ug\VTY^_ZQGDEEB@@ACFJMOPOKHGHFA<98865;CFC?=AGHEB?>>@DFGHGFDCJ]u~ubPF@@BB@=:99<?@@?<9779:962-'#! $/9?BEECA>:64/+),28:<?ELNKJKORSSTSSRQQRROIEEGJNRQNLMRXVNGDEIMPQRSSTUUVVVVVVVUU[dmqrrsw|}vodL>57EWef\QKGGKPSQOLKKLOPPPOONMMNNJCBFLPNGB?=<>@BGLRRJ8$^]\[[\]^]]]]]]]]\\]^^__abdfhhhgghgea^[XVUTSRPONNLKKKLNPQPNJGFGIJKNRV\gu~vi]YQKVm~}pb\WRV]]WNFA=;:;@FNRTTSQNKHGGEA<87754;EGC>>CGFC@?@ADGIIIGFCBK_t{nZLDABCCA>:9;=@BB@=;89;<;850)$" #-8?BEECA>:630,)+1699=DKLGDFJLNPQRRQPOQSPJFEFJNRQNLMRWVPJHIMOQQRSSTUUVVVVVVVUVZbmv{}||~|vgSB>HU]\TOLKKNSTROMKKMOQPPOONMMMKGCCHNQNGA>==>ADINRSL<']\[ZZ[\]\\\\\\\\\\\]^^_`bdfhhhghihfc_\ZXVVTSQONLIIJLNPQRPLHEEHLMLNSY`kxre\[SIMcx
}j[XUMMQOICBA?>ADINRTTSPMKJJJHE@;86644<GIC?@EFDA??ADGIJJJHECAHZmqcRHD at ABCA>;:<?ACCA?<9:<==:83*&#! !,7?BEECA>:630,)+0588:BJIB>AEGHKOQQQOOQSQKFDEJNRQNLMQTTPMLNQRRQRSSTUUVVVVVVVVUV\hw
~~tcRNW^\VRRQPPPQRQPNLLNPQQPOONMMKGCBELQRNF@>==?AFKNPQM>+]\[ZZ[[[[[Z[[[[[[\[\\]_`bdfhhihijigda][ZWWUSQOMKGGKNQQRQOJFDFILLMO
V[aly~p_\[TIGUn}fVSSNMPLIHJJJKNQRSRRSQMJIJJJID?:76644=HHA>BGECA@@CFHKKKJHECACSegZKFECCCB@<::<?BDEC@=::<>?=:5-)%! *5=@DDCA?;740,)*.367:BIHB=@DCDHLOQQPNPSRNHEEJOSRNLMOTSOMORTUSSSTTUVVVVVVVVVVUSV_n{~||~vfZ\fhb[WWUSQNNNPPOMNOQRQPPQQNJD><@FNRRNF@>>??AFKMNNJ<+]\\[ZYZYYXYYZZ[[ZZZZZ\]_bcegijkkjjhfd`][XWURPMKHFGKPRRPOLHDDHLLJLRY_dmz~~~}l`\UPNHH^zxbRNLLPSPNQROPQRSTTUWVSLHHIJJHC<767623 at JE=>EGDBBBCEGHJJIHGFE>=I\_UJFHHHGC=:9:;>CFFEB?;:;?A@<94/)! '08=BCCB?;73/+((+059>CHHDBDECDGJMOPOMORSQMHGJOSROLKQURNLQUWVUUVVVVVVWWWWWWWWUTTYbp}|{{||~}vf_dieac_^YTPNMNPPPPPRRRQOPRQJ>1/2;FMQQOHA>AB at BGKLNMG<.%]]\[ZYXWWWXYYZ[[ZZYYY[]_bcegikllkjihea^[YWUSPMKHFGLPRQONKGDEILKIMT\afnz~}}}j`ZPMTQIUp~o\POOPW]XTVUQPQPQRTWZYTMHIIIIGA9556624AJB:>FIFDEEFGHHIIHHGFE@<DT[VNJJKKJD=99;<>ADEDB@>;;=@A><84-% &.6;@ACB@<84/+(').4:AFIJHFHIGFHJLNPNMNRTSOJHJPTSOKJMQOMPUXWUVWWWWWWWWWWWWWWWUUVW\ix|xyyzz{zthdfd\[bda\WSQPOPPQQRSSSQPPPLA1&&.9DLOPOJA=AC at BGJKMLG>5/^]][ZXXWWWXXYZZZZZYYY[]_bcegiklll
kjhfb_\ZXVSPNLIGHMPRPMKJGDEIKKKPV]cir{~}}
uc`WLN\`VR]y{tgYSWXYbi`UTUSRQPQRTWYYTLHIJJJF at 7235525AIB;?GIGGGHHIIIHGGFFEEA>ALTXVPMLLJE>9:<>>??@@AA?<9:>A@>;60*%""! %-5:?@BA@<85/+(').4;CIMMKIKLKJKLMNNMMNRTSPLJLQTTOKJJJJMSXZWUVWWWWWWWWWWWWWWWVVVVYbovwuvwwxywsnmi]RS\``_\YURPOOPQQRSSQPPPLB5+)/8BJNPPK@:?B at AFIJKJGB=:_^][ZXWVVVWWXYYZZZYYY[]_bcegiklllkkifc`]ZXVTQOMJHIMPPNKIHFEFHJLNSY_gnv}~}}
mYYSJPdoeSLmole]Y\\\hocSOSTRQPQRTWYXSLHIJKIE=4/03536AG@<AGHIIIIIIJIFEEEEDDB?>CMWZTNLLJD=9:<>=;;;<>??;77<@A?951,($"!$,38=?@A?<85/+(').4;EKOPMLMONNNNNMMMLNQSSQNLMRUTOJIHHHKPTWXXWWWWWWWWWWWWWWWWVWWVV[dmrtuvwxyvstujWIKTXZ\][VRONOOPQQRQPQSTSMF=33:BHMPQL?7;@?@FKKJHECA@`_^\YWVUUVVWWXYYZZYYY[]_bcegiklmllkjgda^[YWURONLIJNPOLHFEFGGGILQX\bjs{~}}kVTPLTk{sZLU]``]YWUZgm_OLPRRQPQRTWYWRKHIKKJD:1+,0446 at E@=BGHIJIIIIIHDCCCCDDCA=>FRXTNKKIC<88:<;9888:<;845:>@=620-)%!$*17;=?@?<85/+(').4<FMQQOMOQQQPPONNNMOQSSRPOOSVTOJHIIJJJLQXZYWWWWWWWWWWWWWWWVXXVTV\eotuwxz{xu{|kSEFKORVXXTOMMNOOPQQQQSVVTPNG=:=BGLORL=38??@FKMJGDB@@
a`^\YWUTUUUVWWXYYZYYY[]_bcegiklmmmljhda^\ZXUSPNLJKNONKFCCEHGGHMT[_dmx~}}}rc[TR[p~fQHMSWWSNMTbeXLLOPQQPQRTWXWQKHILLJC8.()/348 at D?>DHGHIIHHGGEAAABBCCCB><AJPOKIHF at 95688887765653138<<8311/,'!#)059<>?><85/+(').4<FMQQONOQRRQQPPPOOOQRSSRQPSVTOIGILMKHGKSXYWWWWWWWWWWWWWWWVXYWTTW`lstvxz{ywkSGDEHLPSSQMLLMNOOPPQSUVSMHGGDCCEGKORM<04=??CIJHFDA@?ba_\YVTSTTUVVWWXZZYYY[]_bcegiklmnmmkheb_][YVSQOMKLNOMIDAAEHHFHMV^bfp{~}}{w~~m^Zbs
s\MKNQSQNMS\\SMPRPPQPQRTWXWQJHJLMJA6+%'-249 at C>>EHFGHGGFEDC@?@@ABCCC@=>BFHHFEC=623455787410/..38:9522441+$ "(/48;=>><950+(').4<ELPQNMNPQQRRRRRQPPQRSSSSRTWUOIFHKOPMHHLRVWWWWWWWWWWWWWWVVXZYUSU]ioqsuwyxzkVKEADILOPPOMMMMNOOPOPRSOHEGKLKIGHKNSM;-2<??@BCDEECB at cba^[XUTSSTUVWXYYZYYYZ\^bcegikmnnnnljgda_\ZWTQNLKLNOMHC at AFIFBDMZehks|~~}}{qmY^ht
{kYPLORTTUY\YRPSSPOPPRSUXYUPKIKLMK?4+&'+/08>@>?EGFGHFDBA@?==?ABCBBB@>;<?CEEDA;5123369;:4.++-/4896235774.'#"(.369;<<:850+('(-3:ELOPONOQPPRTUUVUQQQQRSSSSTVSLHFHKPSQLGGKPUXYWUVWWWXXXXWVWYZYUSTXejmqttvx|~kXNF at DIKNOPPONNOPPON
KJKNNLNTYVQJEEINRM<.0;@@?>?BDEEDCffeda\XUSSSSUWYZZYXWWYZ\`bdgilmnnonnligea_[WSOLJJKNOMIDBCGG@:?Qeptuwz||{||~~~}|{mTKNKR^mu{xcRHKPQU_a_XSRSQNOPQRTVXVPMKKJKKF>72.,-/17;==@DFHHGEA><:9:<@CECBAA>;98;@EFC>9312358=?<5,(*.26974336885.(#!'-1567987630,(%',1:FKNPQQRPOQSVXWWUSRPPOPQQQRROIFGILORROKHFJOVWUSTVVWXYYXWXXYYWURQV_dkturrzziXMEEGKLLMMNLJKPSTROMMNOOQTY]WND?AGMRM>00:BB@>?ACEFEFhiigd_ZVTSSSUWZ[ZYXWWXY\_bdgilnonooomkigc`]XSOLJJKNNMIEBBEE=8 at Vkxzzzzzz{|}~~|{x|x_SPKN^ov{
}iTIJLLS`e`YTRQNMOPQRTUVSMIIIHHGEA>;976678:<?BDFGFDA=;989;>BEFDA@?=:89;?CEC=732347:?A=5,'*/37875346763-(# &-1446776430+'$%*09ELNPRSSRRSTUTQNNQRPNMMMNPQQMHEGJLOQRQOLJIJLPTWWVVWXYYXWWVVVVTRPRYalxwpr}veTIDFKMMLKKJGBCIPTUUX\\XSPOOOKD=<BIORL?21:BC@@ABDFGHHklljgb]YUTTTVXZ[[ZYXXYZ\`bdgilnonooomkigca]YTOLJJLNNMJGC at AA<;G^q{{{{{{{}~{yuzn\RLRbqx~paVPKKVce^VRQQNNOQQRRRROJGFEEDDDDDB@??@><;=?BDFFB?=;:99<@CEGFDA@?>;99;>ADB<633458;?@<5,(*/25765556652-'# &,024566542/+&#$)0:GMOQSSSSSUUTSQNNQROMKJKLMPQNIFGJLORTTSQQOIBFPYYVUUUUUUUTTUVWVS
PNS\myvmp~
r_NEDHMONLKJIFAAEJNSVYXUNG@<:;;::>FNRSL at 32;BC??@CFIKKKooonje`\WVUUVXZ[\[YYYY[]`bdgilnonooomkigda^YUPMKKLMNMKHE@?=;>Mfw~||||||~~{wtzr]SS[jvzwoeYOP^gdZSPPONMPRQPONNLHFFDCBAABA?>>>?=979<?ACC?=<;;<=@DGHGFC@@?><;:;<?A?:533569;>?;4,)*-14566566530+'$ $*.23455431.)$!$*3=HNPRSSRRRSTUWWWWTRPMKJJJLOQOJGGILORUWWUUTMECIQUVUTSSSSTTUVXZYVSNMWkyukm{}mYIBDJMNNNNNNMLJHGHJLLID@<989;?><>FMQRL at 43<BA==@DHLMMMsssrnid_ZWWVWXZ[\[ZYYZ[]`bdgilnonooomkigeb_ZVQNLLLMMMLKHA><:@Sl|~~~~~~{wv{
kXT[ht{|
|tqhYPS`e_VPMNNMMOPONMLKJHGFECBA>:76555663357:<>??>>=>@BDHIHGEB@@??=<;;;=>=842368:<>>:4-**,/145666641.*'$ #(-13455431-(#!%.8BLPRSTSRRRRRRSTUUSROMLKKJKNQPLHHILORVXXWVVUQICEMVYXWVVWXYWWXYWURNNViwulmw{tgVHCFJKKMORTVVSOJFDEFHIHFEFHKNNHA>BIOQLA55=B@;;@EJMNMLvvwurmhc\YXWWXY[\\[ZZ[\^`bdgilnonooomkihec_[VRNMLMMLLLMKFA<;BVn~
|xx}xcQSbqz}|uif^QLS\]XRMKLMMLMNMLKJIIHGFDB@?<520.--.../1479;=>?>>?ACEGGFDBA@@??>=<;::<;632479;<=<93-**+-/2578753/,)'$ "'+02344320+&"!'3 at JPRSTTSRRSROKHGFHLMLJJJKJILQQM
IHILORVWWVUVYYPFBHRYYVTTVYYURPNLJIILQ]lohfkkhaVLGIJHGJNRVYWQLIGFGJLMLIHGIKOQLC?BHNQLA66>B?9:?EJLLJHyyyxtoke^ZYXXXY[]]\[[\]_`bdgilnonooomkihec`\WRONMMMLLMNNKE=;CWo}
}zz}~}u`NResz{zra]UKMX\WSPJIKMLKKKJJIIIHFECA?<;97520.---/0247:<=>>===?@CEDCA@@@@@@?>=;9::952248:<<=<83.+*+,.1479752.+('%!!&*/133331/*%!"*9HQSSTUUTRRQPKGDCCDEEEDEGHHHLQQNJHILORUVUSSUWWTPLJKLLIFFILNLHB=:99<@?DS[WRTY\\XRMLKFEHKNRTSNKJJJJKKHDA=;<=@DB?@FMPQLA77>B>8:?EIKIFC|||zwrmh`\YXXXZ]]]\\\\]_`bdgikmnnooonlkjfda]XTPNNMMLLMNOLHA=F[q}
~||}|{s_LShtxxwr^XQKQ\^XQNKKLMLKHHIIHHGFA@@?=<::8752100001469<=><;::9;<>AA@??@AB?@@?><::9842258;>><:61-*))+-0479641.+(&$! %).123321.(# #-=MUUSTTTSQQMKJHHIKKFCCBBCEDFJOQOKJJLOQTUTSSUTTVXUNH@><9:=?BED<3/0148009A?;<FNTVSOKHGEEGIMOOOONMLKIGB?<9777788:AIOSTMD;9?A<89?DIJHDA~zuojb]ZVVY\^^]]\\]]^`bdehjlmoooonnmlhfc`[UQONNMMMLMKKLHCMduz}~}}|ukWJWmvyyw~iYSOMRYYSNMMNONLHFFFGGDB?>>???<9743210///0148;<=<97655568;;<<>@DCA@@@>>=<8643359=?>;51-)('(*-1587321/-)%"!$(,/0110/,'!"
.>MTTRRQQPPLIHIJLOQPLIGFDBABEIMQQOMLMNQTUUTUUUUWXVPI?==>>@BFHJIE?=EI>61243107=BFFDAABA at BGKNNOOPOMKIFA>=:8665569?FNTUOHA>?>:79=BFHFDB|vqle_ZVVY]_^]]]]]]^`bdehikmnoooooomjgea\WRPONNMMLLKLPNIRhxz|}~zxy|~}}{qdRJ\pwx{{wcVSQRUUQNMNOPOMJGDDEFEC@?ABBA>:63000//.../047:<<<9764334568:<?BEECAA@?>><8643469<?>93.*('&'*-14762110.)%!!$',.0110.,&!!,<JRRPPOONNLHHIKNPRRPOMJGDBBDHMPRQNLMOQTUVVUUVWWUROKHGHJKLMNNONIDDJMJEA>=;:86544321379;@HMONNOPONLJGDBA?><;:89;>DKQTPJD@?=977;?DFECA~xsmf`[WVY]__^^^^^^_`bdehikmnoooooonjhfb]XTQONNMMLLLORQNUgtx{}}xpjhlty|~}|~yl^POarvw}
r^PNOSUSMJLOOOMJHECCDDDBAACEEC@=963110//.../369;;;;9743222248=ACEEDCB@?=<:8655679;=;72-*('&'*-03652110.)%!!$'+-/00/-+'" !*7FNQOONNMMKJIKMOQRSRQPMJHFEEHMQRQNMMORTUUUUUUUTQNKJIJLMNOPPOONJGGKMKJJIGECA>:4.)''(*.5 at JPPNNOPONLJHFFEDDCBA=<=?CINQPJD@?=9669=ACCBAzuohb\XWY]_`_______abdehikmnoooooonkigd_YURONNMMLLMOQOOU`jqx{zsi_Z]gouz||z|}vfWOUgtvw}r`OIJMRROMNPNMJGEDCCCCCCBBEGGHHGGB943210/.-/268:;<<;85210//16<@CEEFECA><:87667789::74/+)'&&'*
,/2441110.)%!!$&*,-..-,*&#!!'3BLPONNMLLLKLMNPQSSTSRPMKJHGINRSRONNPRTUUTTTSQOMJGFEFGHIKLLMMLJIILJDDHHFCACGF at 8+'$#'1 at MSROOOPONLJHGGGFFFFEA??@BGKONJD@?=9679=ACDDD}wrjd^YWY]_`_______abdehikmnoooooonmkie`[VSPNNMMLLMNLKNRV]gqwvodZSU\dkrwxxyyraRO\mvywzzrj\SONPSSQPOMJGFDDDDDDDDEGLNMMMNNI>875421//0369;<=<;85210//049>ADEFECA><:877899::9630,)('&'(),.1331110.)%!!$&)+,--,+)%%$#&1ALQPOONMMMNNOPQRSTUTSQOMLJHJOSTSPOOQSTUTSRQOMJHFEDCBCEFGHJJJHHJKKF??DEA==BILKG?6.'$'1?LSTROOPONLJHGGFFFFEDCA@@BFIMNJD@?=979<>BEGHIytke_ZXY]`````````abdehikmnooooooomljgb\XTPNNMMLLMLHHMNMPZfmnkbYSQTY`hnruwum\NRdrwzwx|xnhjgaXTSTSQOLJGEEEFFFEEEGIMSTQMJIHE@=;976431258;=>>;974322211359>BEDCB@?=<:779:;;:730-*(&&&'()+-/111110.)%!!$&')*++*)'%&&%&1BOSRQQPOOOPQQRSSTTTSRQONMKIKOSUSQPPRSTUTSQLJGEDDDDDDEFGIJJHFDFIKIC>AFD>;>CGJLKF?6/++09ENQQPOPONLJHHHGFEDDDBA@@BEILNJD@?=989<>AEHJL{vmg`ZXZ]_aaaaaaaaabdehikmnooooooonmkhc^YUPNNMMLLMMGGNNHIQZ`ed_XTQOQV^fmrtqiZMUjuvxvx|s`UXYWSSTUSPLJGEDDFHIIGGHJMNOMIDBAAABA@>;986347;=?@?:764334553
114:ADCAA@?>>;77:<=<:70-+(&&&&'()+-/010110.)%!!$%'()**)(&$&('(2ESVTTSRRQQRRSSTTTTSRQPONMKIKPTUTQPQSTUUSROHECAABDEDCDFGHIIEB at CHJGB@DHC;9>DFFHHGEB=5/-1;ELNOOPONLJIKKJIGEDCBA@@BFJMNJD@?=978:<?BFJL|wmga\Y[^`abbbbbbbbbdeghjlnooooopponmid_[WOLMMMLLMLHGMMGGMRV\^\XURMMQW^hqunfXMYoxsuvyzq[JECBEMSTRPKGCBCFGHIJKLLMMJC?=;;=@BDDCA><97559=@BA?95421245763006>EB@@@???=87:==<:6.*)('&&&'()+,/01110/-)$ !$&)*+,+*(&#%((,8ITWUUUUSQORSSTTTTTRRQPONMLJLPSUTRRRTTTSQOKGDBA at BDCAABCDFFFC@?BHIEA at CE?76<DGGFEFIKJ at 60/5?GLOOOONLKKOMIHHHEB@??@CFJMNJE@><9789:<?CHK
{vnhc^\\^abbbbbbbbbcdefghjlnnoppppoonkgb\ULJJJKLMLKHIJKHHILOSVVUSPKJLMQYekg`TO^uypqxzvofSC<;AOUPNPIC>>CGGDEHMQQLG?:6568<@BDEEEB=86568=BDC>740-,.026782/1<CB@@@@@@>:88;>=91,((''''()**+,.031/.-,)$ "&)-//.-*)%!!$)5BLQTSTTUSPOSTTTTTTTSSSSQONLLMNQRSTTTTTRNKHFFFDBA@@???ABDDDCA@@DHIEBAB@:55<DHGDCDHMNIB;67>FKNNONNNMPPNJJLKF?<<>ACGJMMKE@=;999;;;<@GL{wnhc_]]_accccccccccdeefgilnnoppqqooomic^WMIHHIJLLKJJIIHHHJKNPQQOLIGFCBFNW]ZQPbxzppy|vqjWE@@FTWOLLF@>?BDDBAELPNG=73
3347;?ADEFEB<74347=CEC>83/+*+.0269601:AB@@@@@@>;88:==93+('&&'(*++++,.021.,+,*%!#'+/110.+)&!",<HLKMOPRTVVUTTTTTTTTSTTTRPNMMMNPRSTUUSQNKGEEGGFDB@>>>?ACCCCBAABEIIEBAA>856=DHGDBCFJMKGB>>BGLNOOOOOONMOSVTMF@;;=@DGJMNKE?;9:;;<<;;?GM{wnhc_]]_accccccccccdeefgilnnoppqqppomid^YQLHEEHKMMLLKIIHGGIJLMLKIGGFC?@DLTSNTh{|rr{{uiUEBFOYZPJF?>BBA at AABEIJF>5001236:>ADEED@;52226<CFD?94/+*+.//498328>???????>;88:==95.*'$$'*-/.-,-./00-+,-,'# $(,/110.+)&##1BIGCBDDFJQWYVTTTTTTTSTTTRPNMNNOPRSTTTQMIGFGGHGFDB@?>=?@BBBAAAABEIIEBAA>857=DHGDBCFJLKHECCEHLOQQQQQQNLNTSMFDB=;=?CGKNPLE=99;<<<<;;?GM{wnhc_]]_accccccccccdeefgilnnoppqqpqpnjd_[TNHCBDHKMMLKIHGGHHIIIIIF?>@?==AHPONZpvu{vfQEFNX]ZPH@:=DE@<>BEGHGB:2/0357:=?BCDCA>952226<CFE@:50,*+---1786469=>>>>>>>;979;<:62-(%%(-110/---.//-+,.-)$ !%)-0110.+)'#%7FG@<9977:BNUUTTTTTTTSTTTRPNMNNOPQRRSQNIEDFIJJHGECA??>?@ABA@@@ABEIIEB@@=857>EGFCABEIKIHGGGGHKORRRRRRQOKHEDDDB?==?BFJOPLD<88;<<<<;;?GM{wnhc_]]_accccccccccdeefgilnnoppqqqqqoke`\VPICABEIJJJIHGFGHIHHHHHC8575336?QON_uz
x|u`MFJW__WMD=8=DE@<>DHJJGB;537:<>@BCCBA@>;864458>DGEA:60,**,,,/476547;>>>>>>><977:<:851,)),1431/.../00-,-/.*% "&+.1110.+)'$!*>HA99874//6DOTTTTTTTTSTTTRPNMMMMNNOOONKHEEGKMLJIGECBA at ABBBA@@@ABEIIEA@?<858?EHEB at ADHJHGHIIHGJORRRRRRSRLIPZ[NC?@?>@DHMOLE>99;<;<<;;?GM{wnhc_]]_accccccccccdeefgilnnoppqqrrrplfa\VQKEA at ACDEEFFFFGIHGEDEFEA?=9447>XOM`u~}{z{~pYIGO^d]QHA;:>BBA at AEJLJGD@<<>BCEFEDC?=<;98889:<AGHFA;71,))+,,-145435:========:669;;9852//25630///0122/../.*$ #(,/1110.+)'$$1DE73;<;70,1?LSTTTTTTTSTTTRPNLKKKKKKKKKIHGHKNPONLJHGEDCDDEDBA at AABEIIEA?><858 at FGEB@@DHIHFFFFFFINQQQQQQRQPXk}x\FBDA>>ADILKF@<:99;<<;;?GM{wnhc_]]_accccccccccdeefgilnnoppqrrsrplga]VRMHC@=>?@ABDEFFGFC@@@BDFGD?<?EQXNJ\pwvx|{|{jRFIScgYJD>;?@>?BDDEIJIGECCCDGHIHFC@;99889:<>?@EIIFA<71,))+,--.034359<<<<<<==:668;;::97667972///024552///-(# $).11110.+)&$'8IA-.<=97/),:IRTTTTTTTSTTTRPNLIHHGGGGGHHJKMOQRRQPNLJHHFFGGFDBAAABEIIEA>><869 at GGDA?@CGIGEDCCDEHMOOOOOONNOYkzv`OIHC><>AEIIGD@;87:<<;;?GM{wnhc_]^`bccccccccccdeeffhlnnoppqrrssplgb]UQMIDA>
><<=?ABDDED@>=<>>><;:;?JYYLFShlry~|{wfMDJXdeUE?<<BA<=BFFGGHGEDDEFGIJIGDB>8789;=>@BCCFHHFB=82,)()+,+,.02138;<<;<<>>;768::9:;<<;:951../0358731/-+&"!&*/12220.+)'!(=K>(,>411+&)6CPSSSSSSSSSTTRPMKHFFEDEDDHJLOQRSTSSRPNLKJJJJJHGECBCDFIIFB?>;87:AFFDA?ACGIFECBBCEGLMMMMMMMKJNXcf`XSKB><=?DGHHIHA;69<;:;>FK~zunhc_^^acccccccccddddddefjlmnoqrrqrrpmhb]TPLHECC@;9::;=?@BA@>=<<==87;;<JXWKBCHXerz{{t^GCP_d^OA;=?@>=>BEGGGEDCDDEHKLKJHEC@==@CEEEFEDCBBDDC?;5/*(())**+-./16:<<;:=?><:87888:<?@>:40.-,-/378630.*'#!&*.134320-+)"'?J<(+41.,($(5CORRRRRRQQRSSROLIEDCBCCDGJMOQTUVVUTTRQPOPOPOMJHFEEFHJKIFDA>;88<BEDBAABDFFEDEFFEDEGIHGHIJIHIMSY^ac[M@<==?CEFJRWSC99;;::>BE
}zumhc`^_bdccccccccdddddddfiklmopqrqqqplgc]TOKGDDEC=:9889:<>??>>>>?>98===JXWLC<<DN[mx}sX at ATccZL@<@B@=>?ACFGFEDCDEFJNPOMKIHGHJMOONMJEA?>>@CDA=82-*)()**+,-./48<<;:=??=;97778:>AB?92/--,,/378530,(%"! "&+/244542/,*(#(>I?-(042+# '6DOQQQQQQQPQSSROLHDCBBCDFIMPQSUVXYYXXVUTSSSSQNLIGGGIKLLJGEC@<9:>CEDBBBCDFEDDFHHFDBBBAABDFFFLSTQT^g`M><>=>CEFKW`[I<9;;:<>AC}yunid`_`cddccccc
cccccccccehjklnopqpppokfb\TOKFCBCB>;97666788:;=>?@>99=?BNWSJC=98:AP`lgO;BXb^UH?=BD@=>@BDEFFEEEFHJNSUTRPNMNQSSSQNLG@;:9:=@CCA=72.,+++,,-../38<=<;=??=;97779<@CDA:3/.-,,.26752/+(%$%&),03566420.+(&#$*:IF4(*.-#)<JRRRRRRRRQRTTSPLHCAABDGILPQSUWY[\^^][ZYXWVTSPMKIIJLNONLIGDA><<@DFEDCCCEFFDEGIIGEB=<<=?ADCCKQI>BXjbL><><<ADFMZd_M?;===>ACD|xtniea`acddcccccccbbbbbbbcgijklnoonoomje`[SNJEB at A@>;96322100257:<=;99;@GRUHCBA?=;76=JPG<CTZUKB<=BC><>ACDEEEEEFHKNRVWVTRPNNPPNKGC@<854469=ADD@<741/......//26<>=<>?>=;97779>BEFC=61.-,,-04541-)'&&(,/24778630.+)&$#$&4GL>-&#!%5HRUSSSSSSSRSTUSPMHB?@BEILORSUXZ]^_aa`_]\[ZYWVSPNLLMPQRQNKIEC@?@BFGGEDDDEFFEEHJJHEB><<>@CFFCEE<6 at YjaJ<<=;:>CFM[fcRC=??@ACEE
{xtnjfb`bdedcccccccbbbbbbbcfghjklmnmmmlhd_ZSNID@>>><:741//-+*,.14677779ALTQHDFHHFC=4.5AE@?FKH@;9;>><<?BDEEDDDFHKOSUWVUSQOMLLJFB=9652100259=CDB?<96410000///05<?>=>?>=;97779>CFHF@:50-,+,/243/+(&'(,035787750.,)&$"!! ,DPH7,%$'/:GQUUSSSSSSSRTUVTQNHB?ACFJNQTVX[^`bcccba_^]]]\ZXURPPRTUUTPMJGECBCEHIHGFEDEFFEFIJJIFCA at ABDHJLKD<:BRdj]G:;>;:>CEKYe
dVH@@BDEFFG{wtokfbabefdcccccccaaaaaaabdfghjklllllkgb]XRMHB><<;:852/.-,))*,-/002545?NUPIGHHHFEEA87AG>34;=88:<<:9;?CEEDCCDFJNSXYWUTRPNLLJHC?:86520/./25:?AAA@=;85321100./4<@?>>?>=;97778=BFIHD?91-,++.131.*&%'+.35666431.,*'$" (@PL at 8349CMTTSTTTTTTTTSTVVURNICABDGJNQUXZ]adfggfedca`aba`]ZXVUVWXXVSOKHFFFFHIJJIGEEEFFFGIKKIGECCCDEHJPQI>CVflgUB7:><;@CCGTadZMCBDGHHHH
~zwtokgcbcfgdccccccba``````acefgijkkkkkjfa\XQMGB=;:97520.---...----,.222>PULD@??@BDHGA?EC4((4669?@<87;@DFFDBCDGKPV[\YVUSQONLIEA=:99841/..036:=@BBA?<7443210..3<A@???>=;97778;@FJKHD=3.,*+-021-)%%(,0345431/-+*(&# )?MKD?87<FQVTRTUUUUUUUTUVWVROKDBCDGJMQVY\_cfikkkjihfffgfeb_][ZYZ[[XUPMIHHHIJKKKJHFEEFFFHJLLJHEB@@@ACDKOICL]he[M=59>==BDBCN\b\PECGIKJIH
~zwtokgdbcefdccccbbba``____`bcdfghijjjjiea]YPLFA=:99531/.../010/.--+.211?RTF<74349CC??CE;+#'256;@@<88;>BEEDCCDHMSY\\ZXXVTRPMFB>;9999531/./137:=@BAA?9653210.-2;@A???>=;:8777:>DIKIF at 4/-++,.00-(%%',/2221/-+)((&$" !,>JIEA505?KSTSTUUUUUUUTTUVUROLFEFFGJMPWZ]afjlnpponmkkkjjigdb``]]]\ZVRPKJKKLLMMLJIHFFGHGHJK
LJHDB>:67;?FJHDKW\WPG<68===BDBAJXb^RGDFIKJIH{wsokgdcbbbccbbaaa`__^^^]]]`abcefghgggfda]XPJE?;997200//../000//--/1556FURC:61,,/.1:>DA5(%,3779;;988:<=@ACCCEJQX[\ZZZZZXTQLEA@><::96420/002479<?ACB<9631/.--07=@@?=<<<;98668<AEGFD=5/-+++-.0.)%$&)-11/-+(&%%$##! %1?GIG at 614=HQTSSSSSSSSSRSSRQPOLHHIHHHLQVZ_dimprssrqpononnlkigfeaa`^[YWUPPPOOPOONLJIIJKKJIHIKJFEC?7227?GHEBEMRRNE?:9:;=@CBBGVc`RHCCFHJIF{xtnjgecbaabbba``__^^]]\[[\^_`bcdeffffec`]YPJE?:885200/////////00016::>LYRA9730038:=AD=2+.3688888889:;<>@CCBDKRX[ZYXYZZXTQLGDCA?=;:74310012579;>@BA>:731/.--06<@@?=<<<<:8657:?CEDA<40.,,,,.0.)%$%(,/0.,)'%$##""! &3?HJHB847?IQTTSSSSSSSSRQQPPOOLIIKIGHLQVZ_ekorsttssrqppponljihgdcb_][ZXUSSSRRQPOMLKKLMNLIHIKJFCBA><<>ADD@<>HQWTH@<98:<?ACBFVdbTGBACGIIG{xtnjgecbaaaaa`__^^\\\[ZZYZ\^_`acdddddca^\XQLE?:6540////000011245579=?FRZPA97557=BEDDC;206;979999779:;=?ABA at CJQVXXWXXXWURPMIGFDB@><8542223478:;=?A@=:731/.--06<@@?=<<<<:86569>BCB?:3/.,,,-.0.)%$%(,/0.,)'%$##""! &3 at HKJD958?IPSSSSSSSSSSQQQPOONLJJKJGHLPVZ_ekorsuuttsrrrqpn
ljhgffecb`^][XVVUTSSRQONMMNOONKIJKJFA?CHLLHC?;858CP[]E><99:<?ABAEUecUGB at BGJJI{xtnjgecbaa``__^]]\[ZZYXXWXZ\]^_abbbbba_\ZWQLF>85310/00111233568:;<<>BKUVL@<;978;>@CDB=76;=979::97779;>@AB@?CKQTTUVWWVTRPNMKJHFDBA>965445679:;<=>??<:731/.--06<@@?=<<<<:86558=@A?<81.-,,-./0.)%$%(,/0.,)'%$##""! &3 at ILKE:68?IPRRSSSSSSSSQPPOONMLJKLJGGKPUZ_ekorsuuuuutttsrpmkigfggfdca`^[ZYXWVUTSQPOOPQROLJKLJF@>CLSSLC=8513<JX]A=;99:<>@A?DUefWIB?AFJKK{xtnjgecba`_^^]\\[ZYXWWVUUVXYZ\]^_````_]ZWUPKE>842111123455789;=>@@>>CMTPFABB=84114;AB@=::9679<<97569<?ABB@@FOSRQRUVUSQOMLLLKJHFDC@<98889:;<<<<====<:731/.--06<@@?=<<<<:86547;>?<950.-,,-/10.)%$%(,/0.,)'%$##""! &3AJNMF<79 at IOQRRSSSSSSRQOONNMMKKLLJGGJOUZ_ekortuvvvvwwwvuspmjhhhihgfedc_^][ZXWVUSRQQRSTQNLLLJE@?CINNIC>:7205?MR?;:::;;=?@>BTfhZKC?@DIKK{xtnjgecba`^]\\[ZZYWVUUTSSTVWXZ[\]^^^^][XUSNIC=74333345789:<>>?ABBDC at EORKCDGHB:3-*-8>?><97446:==:6458<@BBA at CKTVQNOSUSQNLKKKLKJHFDCA?==<=>@@?>==<<;<;:731/.--06<@@?=<<<<:864469<<:63.-,,,./10.)%$%(,/0.,)'%$##""! &4BKONH=89 at HOPQRSSSSSSRPO
NNMLLLKLMJGFINUZ_ekortuvwwxyyyzywtpmkjkkjjihhfcb`^\ZYXVUTSSTUVSPMLMJEA?AEGGEA?<:6105?C=99::;;<>><ASgj]OF@?CGII{xtnjgecba`]\[[ZYYXUTTSRRQRTVWXY[\\\\\[YVTQKGA<75445679:<=?ACCCCDDGIEHQSICHLKG@:403<>95444346:>>:6448=ACCA at GQZYRLMRSROKIIIKKKIGEDBBAAAAACEDA?>=<;:;;:731/.--06<@@?=<<<<:864358;;841-,,,-.011.)%$%(,/0.,)'%$##""! &4BLPPI>8:@HNPPRSSSSSSRPNNMMLLKLMMKGFHMUZ_ekortvwxxyz{|}}zwspmlmmllkkkifdca^\[ZXWVUUVWWUQNMMKEA>@DFFD@>;;82-/6:979:;;;<>=;@SglaRIB?AEGG{xunjgeca`_[ZYYXWWVTRRQQQPQRTUVXYZZZ[[YWUROJFA<8766789<=?ABFGFFFFFILJLUSHELNLHDA>;=B?61024537<?=84248=ADCA at JW`[QKOTTQLGGHJLJIGEDCBCDEEFFHIHDBA>;99;;9631/.--/5;??>==<;;:9642256641.-,+,--/01.)%$%(+01/,)'$#""!! %4CLONI>9:?GMOOQRRRRRRQMLLKJJIILMMJGEHLTY_ejnqsvwxyz{{|~~|xurponmmmmllkhfdb`^\\YXXWWXYYVRPOMJD?=AGJIE@>9871--16778:;;;;<=<@QfleXNC>?CEE~zwrligda`^[XVVUTTSRQPPPOOOOQQRTUVWXXXXXVSQNIEB>;989:;=?BDFHIJJJJIILMKPWQDDMOJECCDCDD at 94467439AB<40259<@CDAAL^g^PNSWRKEBCGJIGDCBABDGHJKKMMMLIHE?:78:9851/--,+.38<====;:9:973/.//.-+*+++++,,./,($#$',/0.+(%#!
%5CLNKD;78>FMOQRRQPONNKGEEEEEEHKLKIGFGIQX`fikosuwyz{{{{||zxutrpmllllllkigfda_]\[ZZZZ[[YUSRPMHC>=AHJHB>:531.,-03667899:9:>??K^hh_TF==ACD}yvqkhfca^\ZVTTSSRRQOOOOOOOOPPQRTUVWWWWWUSQNIFC@=<;<?ACDGHJKKKKKKKKLLLRVOCDNOIDBCEDDD@;899844;CB:2/17:=@CDBCNai`TSVSKDA at CFEDDBAABDGHJKMNOONMKJG@96799630.--++-38<>>>>;889962-,,+**)**++++++,.,($#$&*./-*(%#!$5DLNJB946<FNRSTRQNLIHFBAAAAAADJLJHFFFIOW`ehjnrtvxzzzzzyyxvusrqmllllllkjhgeca`^]\\\]]][USRPLGB><@EE at 9631/.../02567889:9:>?=FWadaWH>=@BC|xtpjgeb`][YUTTSRRQPONNNNNNNOPQRSTVVVVWWUSQNJGEBA@@ADEFFGHIJJKKKKKKKMNSUMDFNOIDBCEDDC?;9::856=DB91/37;>ACDDHTchb][WMB==?CC@>@BBBDGIJKKMNOONMJIF at 9579742/-,,+,.4:>AAA>:779961-++**))))******+-+(%#$%(++*)'&%#$5DMOLC825<FOTTSQNKHDB@???????CIKIGFEFHNW_egjmqsuwyyyyxxwwutsrpmlllllllkjigecba_^_^^^^\VSROKFB>;>A>7/*)),-/011246778999:>>:@NW[^XKA>@AB~zvrnhfda^\ZXUSSRRQPONMMMMMMMNOPQSTUUUVVVVTRPMJIGFFFGFFEEEEEGIKKKKKKKLPTRKEHNNIDBCEDCB>::;;869 at D@70048<@BCDGMZehedd[L@<:;>@>=?ACDGILLKKMNOONLJIF?8568520.,+,+,/5;?BCB?:879961
,+**)((()))))))*+*(%$$$&'('''&&# $5ENPMF:46<FNRPLIGEC@?>=======AHKIGEEEGMV^dgilprtvwxxwvuuttsrqpmllllllllljhfdcbaa``___\VSPMIEA>=>?:1(##%)-0220135667889:><6:GNSZYNE@?@A}ytokgdb`]ZXVTRRQQPPOMMMMMMMMNNOPRSTUTUVVVTSRPOMKJJJKIHHGGFFGJKKKKKKKLRUOHFJNNIDBCEDC@=:;<<97<CD?50159>BCBDIR^hjhij`RIC<9<?ABABEGJKMLKKMNOONLJHE>746630.,+*++,05;?BBB?<99;:72,**)(('(()))))))*)'%$##$$%%%%%%# &6FOPMG>99=EKMJDAAA@@@@???????CHJHFDDDGMU^cfhloqstvwvvussrrrqqpmllllllllljhfdcbbba`_^^[WSOKGDA@@BA;2)%#%(,/110025566788:>;57CJOYZRIB>?@|wrmieca^[YWUSRQQPOONMLLLLLLLMMNPQRSTSTUVVUTSQPMKIIIIJJJIIIHIJKKKKKKJLTVMEGLNMIDBCEDB>;:<>=98?EE>4/27:?DDBDLVajljkmf\UOE at ADGFEEGJLLLKKKMNOONLIGD>63561-,****+.15:>??@@?<;==:4-))((''''((((((((('&$#""$%$$$##" )8GOPKF@;;>DIKHCAABCDDDCCCCCCCEIIGEDCDFLT]cegknpqsuuutsrppppppomlllllllkjigecbbaa`_^]\ZVRNIEBAABDC>5.+*))+-./.0244566779=;58DLPX[VMD>=?{vpkhdb`]ZXVURQQPPOOMLKKKKKKKLMNOQRSSSSUVVUTSPMKGECCCCCCCCDDFIKKKKKKJLVWKDHNNMIDBCEDB=;:<?>:9AGE=3.27;@FEBDMXblpkjmke`ZRNMMLIFGJLMMKJJKMNOON
LIGD=63440,*)))*,.159;;:=AA?>@@=6-)(('&&&'''''''''''&%#!!$%$#"!! ",;HONJC=99=EKMLKJIIIIIIHHHHHHHIIIGECCCEKT\begknoprtttsrpooooppomllllllkjhgeca````_]\ZYXVRMHDBAACDD?8311.,+*+,-/234556678<;6;HPSX\YQE><>}ytnigb`^\ZWUTRQQPPPONMMMMMMMMLMNPQRSSRRTTTTSQKFC@=<<<989:<=>BGJIJJJKJNUSHCHMLMIDBCEDA@=;=>>;;CHD;3/36<AECAGQ[dlojimnkfb_\ZVQLJKMNMLJIKLNNOOMLHFA;6332-))()*+,.26:;:9;?@??A@>8-)(''&''&'''''''())('%##$$$#"! &2 at KPOJC:77=FMPQPOONLKIHKLLLLLLLKJGECCCDLT[adgjlnpqrsrrqonnnnnnnmkkkkkkkigfdb`__^^][ZYXWUQMGCAAACEC@:7541/,+*+,/35642257:=;6:GRVZ]\RD;<?~{vqlhc_]\[XWVTRQQQPPPPPOOOOOONNNPQRSSRQQPPNMLHB>;87788779;=@ADFGGFFHINRQLECGIJKGB at BDDC?<;;>><?FGA9213:@BAADLW`fhhfdfhhfffeb^YUQQPONKJJKMNONMLJGC=9631+'&()+,,+,19=>=;<===>?>=7.('$$%&&&%%%%%%(*++)'%$#!"!!! "-<IMNOJA967<DLOMJIJJJIHJMNNNNNNONKHEEDCFMUZ_begjmnnoooomlkkllllkjjjjjjjhfedba`^]\ZZYXWVVSOJEA@@CEEC@>;96410.,,,/5:;8425;;<96:ES\_baTC9;@~|xtojgc^\[ZXWVURQQQQQQQQQQQQQQPOOQSTTSRQONKIGFC>:9779;<>?ACEGHIHGFEDEFLRPHDEGHHGD?>@CC>736:>=87HF>6225;BCABHQ
\aca`_][Z[`cddc`]ZVTSQOMLLLNOONMKJFA<864/)$$'),--+,1;AA@@@>>???>=8.(%#""$$%%%%%%%&)*('%#" "3EONKKF=8669 at FHC=<@DHKMNOPPPPPPPPMIGFEDGPVZ^befhlmmmmmmlkjjjjjjjhhhhhhhgedca`_^\ZYYXWWVTPLGCA@@BEDBA@?=;6420.,+-4;?@>;;;8789>JZdhjgZG::>|zvrmifb^\[ZXWVURQQQQQQQRRRRRRRRQRTUVUUSOMKHEB@><;;;<>ACGHIIJKLKIGEDDDEKQPIEFHIHD@<<?BC>99 at IOLDBFE;4139>BBCFLU^`\ZZYVRMNUZ]_``_]ZXVTRPONMNOONMKJFB>;95/(#$'),--,,2=CEEEEDCBA@?>9.)&#"!!#%&&&&&&')*)('&%$"""""""""! !'9JPKFE at 97647<AB?=>CHMQSSQPPPPPPPPOMJHGGKRX[_cefgjkkkkkkjihhhhhhhgggggggfdba`_]\[ZXXWWVVSLHDA@@ABDDBA@@ABA@<840-+*,17;:4/-/248 at KTZ]\TG=;<xwtpkgda^\[ZXWVURQQQQQQRRSSSSSSSSTUWWVUSNKIEA>;:;<=?ACFHIJJJJJIHECCDEGINROIGHJJHD@<<@DEDDEJQVUOKGC:204;???CIPX^^WUWXVQKJNRTX[]__\ZYWUSRPNNOONMKJIFCA?90)#$'),--,-4>FHHIIHFDB@?>:3.,)(&%&)******,.000///.,,,,,,,---++++-1>KNGAB?96436<ACEJNPRSSSRQQQQQQQQQQPMJHJOUZ]`cdefhiiiiiihgfffffffeeeeeeedb`_^\[ZZXXWWVUURIDA??@BEFGFC??ADEC@<73013338?@93478520357:>@?===utqmifca]\[ZXWVURQQQQQQRRSSSSSSSTUVWWVTRMKHD@=:9;=?BEGHHHGFFEEDCA at BDHLORSOJIK
LKIFB>?CGHGFCABFHGFFB:325;=;<CLTZ^\WUY[[WSOKKNQUY\^]\ZXVUSQNNOONMKKKJIHE>3*#$'),--,.5 at GIJKKHEB?===<865421//01111112456677776666666777655679 at IJB>BD>6238 at FILSVWVUSQQQRRRRRRQRTUQLJMSY]_bcddefggggggfedddddddbbbbbbba_^]\ZYXWWWWVUUTQHCA??ACGKMKE><?B?===>>>ENMGGLMICBCC=4,)&!!&/7<<;rqnkgdb_]\[ZXWVURQQQQQQRSTTTTTTTTUUVUTRPMKIFC@=<<>ADFHHGEDCCCBBBABDFJOSURNKJLNLKHD@@CGGGD>647=ACDA;656:98;FQZ_a_ZZ\^^][UKHIKNSVZ\\ZYWUSQNNOONMKKKKKKH?2("$'),---/7AHIIIHD@<:89;<<=>>><:9::::::::889:<==>>>>>>>>???>==>?@DJI@=CHC934:BIMMNOQSSSRRSSSSSSSRSVXUNLQX]_accdccdeeeeeedcbbbbbbb```````_]\[YXWVVVVVUUTTPJEB@@ADGMQNF=:@DDCFIMPRRMF?:99754673,&$#! )5<;8polifca_]\[ZXWVURQQQQQQRTUUUUUUTTTTTSRPNMLJHFDB@=?BEGGFFEEEEFFFGHIIJLORSRNKLNOMKHD@?ADDC>71/4<ACCA=:87767>KXbffd`^^]\[ZVLGGGIMQUZ[ZXVTSQNNOONMKJHIJJG=.%!$'),---08BHHGGE?:64469<>@CEFECBBBBBBBBA@?ABDFGHHHHHHHHIJJIHHIJJKNK?<CJF<66:AHJJLNPSTUUUSSSSSSSRSX[WPNS[`abddcbbbccccccba```````_______^\ZYXWUTUUVUUTSSQLHECBBDGLPOG=;CKMLJHFDB<2.-)#!## $&"'5?>:mljgda_]]\[[YWVUQPPPPPPQTTTTTTTTRRRRRPNMNNLJ
HFFD@@BCDDFGFGHIJKLMNNNMMMNOPNKLPQMJD@>@A?=;6/+*07=@CB>;97649BR`hjifc`\XUTSQKGEEFJOSY[YXVTSRNMMLKJHFEDEFD:," $'),---19BHHEDA:5201369=ADFFEEDCBBBBBBBCCDEHJLMOOOOOOOPOONMNOPNLMJA=CIF@:8:?EIMQUVVVVVUTTTTTTTSSX]ZSPV]bccddccbbbcccddc`__^^]]]]]]]]]]\ZXWVVTSTUUUTTSSRMJHEDEFHHKMICAGMKD92*#(173*"!! "%%#1<?=igfca_^]]]][YWTRONNNNNNPQRQPPPQPOOPPONLLMLKIGGGGDB?>?BEGHIIJLLMNNMMMMMMNNKILQQLC=9<BB822/,((,4=EEB=:9853:GZhmkgdc_YSNKJIHFDCFKQX\\[XVTSPLHFFFFB@@@@AA9," "&),..-08CHGCA=7310/0359=BCAAA@?>>>>>>===>?@?@?@??????@IIHFDEEFHGFBACDD@<87;AHOSUVVVUTUTUUUUUUSSX^]YVY_deeddddeddcddded`^]\[ZYXZZZZZZZYVUUUTTTTSSSSSSSQOLIGFHJJHKMKE at A<,%'" $/53*" !!'/46eddba`_^^^^\ZWTQMLLLLLLMOONMMMNNLLMNNMLJHGGGGGGHGB;:?CEGKMLKJIHHIIIJLNOOJFFLQPG?97<B?1(('&$%,6AGGA;88864<J]jnkfddb\UNIEDEEDEIPW]a`^ZVROLHDBCED@=>>>@?8,# "&),..-08CHGC@<6321001237=?>>@A@??????>:9::;<<>@AAAAAABEEDCCCDFHHFDB?>><:524;CJORTUUTRRUVVVVVVUTY_a^[]aefeeeefgffedcbba_^]\ZYXXXYYYYYYXUTTTTTTTSSSSSSSROLJHHJLOQQNG=4.)%#" !! $(&! #'*cccbbbbb``_
^[WTPKIIIIIIJKKJIJJLLKKLMMMLJGGIJKKJJGB<;@DCDHKKKJJJKNNLKLNQOGCHPVSF;315=<1+.10/05=FJE?:99976?N`lokgfhgc\UMFCDEFJPW^cge`ZSMHEA at ACFEA>=>?@>6+# "&),...08BHGC@=8431111238 at CDEGIIHHHHHHHHHHIJJKLOPPPPPPPOOPPPQQPNKHC>956650-.28>DJPUWURQTVVVVVVUW[`ba_`befffggghjjigdba`__^][ZYYYYYYYYYXUTTTTTTTSSSSSSSRPMKIIKMRTQG;/%"$" ! !!aabcddedcb`^ZVRNHFFFFFFGGGFFFHIJJKMNONMMLMOPONLHEDDA?>?ACDFILNPRSQNKJLOMGELV\XI9,',7932530.-/38>CB<:;:88BQalokgffgeb[TLHGHLQW]bgihbZQIC?<<>BFFA=<?A@<3)" "&),...29BFFBA>9642111005<AAABCBAAAAAAACDDEFFGHHIIIIIIHGFHIJIIIHFB=83/023/,+-026=GPUVSSTVVVVVVVVY^abaabdfggggfgijigfdca_^]\[[ZZXXXXXXXWUTTTTTTTSSSSSSSRPNKJJKNQOH:.&" #$#! !! aabcefgfdb`]XSOJDBBBBBBCCDCCDFHJLNPRSSRQRRQOMJGCAHOJ>8=CDCDFIKMKGDCCEILJEBIRYUH;0*,21*()$!#'-49BKKB=<<:;FTblmjecbccc`[WSOPTY^acfhf`XOGA>;;;?CDA=<?BA:0'" "&),../29AEDBA@;863211.,/7;:87877777776333445677888888778:;;:99:;9630./230.-,,++0:ENSUUVVVVVVVVUVZ^ab`acfgggeca^^^^___^][[[ZZYYWWWWWWWVUTTTTTTTSSSSSSSRQOLKKLOQLA2'##"#%%#! !
bccdefgfca_ZUOJEA??????@BBBBDFHKPSUXYYYXVSOKGEDBCKSOB:=CDCBA?><9216<BGLJA<>FMMC><8451'$+3:CO\gpqfYKA==<>GTbjjgc`__`aa`_]Z\_bcb``ba\VOIDA=;9;?A@=<@DA8-%!!"&),../3:ADCBBA=974211039AFEB at ACDDDDDDC@@@ABBCEHJJJJJJJJKMNMKHA732110/02321/-,)'(/7AJRVVVVVVVVVUUW]bda`bfgfd`\XRPQQRSTUWXXXXXXXVVVVVVVVTTTTTTTTSSSSSSSSQOMKKMORL?.$"#!!%&$!! !"##ddeeeffeb_]XRLFB=<<<<<<>@BBBDFIMTY[^_``_\XRLJKMNMMNNLG@;;;9641/./3:BGJKIA;8<DGC@>:;CFEIVhr{
xhUE>=>AIT`ggd`___^^_acdegiifa[YZZWSOKIFB<87:>?==@EB7+#! "&),../4:ACCABB>;8531128AKQQONOOPPPPPPPNNOOPQQSWYYYYYYYXY[\ZUQI7222222211221.,**)(+2>JQVVVVVVVVWWX^ehebcffeb\VQNMMMLLLMRTUUUUUUVVVVVVVVTTTTTTTTSSSSSSSSRPNLLNPPH9)"#%""&'$!## !! fffffffe`]ZUOHD?<<<;<<<=@ABDFILQY]`bcdddc^WUUV]b[RLNSQC60/-++,-1>FJNOLIGEA>@EHE@=4:Nbnz
qZI@@BEJS_fdb_`__^^_acgknpmg^VSXXUPMJJID=97:>@?>CHB4'""!"&),./06;@BBABB?<8531104;ELNLKJHGGGFFFD@?@AAAACEGGGGGGFDEFFD?:74455445410121.,,-,)(,5AJTUVVVVVWXX[cnplfcdffb\VSUVTROMKKORSTTUTUTTUUUTTTSSTTUUUVT
SSSSSTSQOLKLOPN>/$!$('%')($ %))# fffggfeb]ZVPKE@?===>>>?@@ACFJPTZ^bdfgggigb_cq|ul`UMOUTJ</*)(,18DNTUTRMIGHIIKLIEFB9=Ywr^KA at DFJS^cb``a`_``acehkpqmcZVZ\[SLGFGEB?==>@BCBFF=.$$&##%'*-059=?AABCCA=9521137>EKLKGECCBA@?>=;::::;;=?@@@@@@@>=>=:73236766566212100.-+,.+*.7DQTTTUVVVWV]m~ylcdhhgb[[Z[XSOKHILOSVWUTQOPPQPONLMNOPRSUUSTTTTTTSQLIJNOMD6*#"%(().0-& !!!%)+'#! ! ggggfdb^YURLGB>=>??@ABBCBCFIOTY^cfhijjiijijqxwmaTKGJRUQD5./3:DMTXYWUQMJIKNQSQMHGGBJf}}yvx}xm^MA=@DJS]bbabca`aabcddgjkf^YZ_a]SJDCEEBAABCDEECA<4-+,,&$%'*.26=@@ABCDDB?;62115<CHLMKGDDDCA@?>=<<<<<<<>BDDDDDDDDCB@=853457665665443221.**,)&)4BOSTTUVVVUV_srfeikjfa\VSQMJGEEHMSXYWSPMLLJIHGGGHIKMNOQRSTTUUUUQMLNRPKA2)$#&((+?;/%! ! #'(&#!!!!! gggeb_\XSOLHC?<;=?@ACEFGGHKNSX]agjlmnnmlotz}xm_VNIGLTYWNA=AGOW]_^[YVROLLORTUTQNJIM^vzurrrpnpvxtpi[KBBFKS\bccdedcbbaa``aa`\Z\bfd]SJDDFGEDEEFGGIF</,3;<5)$&(,048?BBCCDDEEA<74226?FKNOLIGGFEDCAA?>======?DFFFFFFGGGEB>:54345665434432211/,./,*/<HQRSTTUVWY\ewwjgkmlie^
RMKHFEEDFKTZ\XROLKGB@?@BEGHIJKLNPRSTUVWURQSVVPF;.'##&**,C9( ! "%&#!!!!!! feca\XTPJHFB?<:9<>@CFHJLMOQTX]afknpqrrqpr{te[Y[ZWX\][VSTWZ]_``_]ZVSPNOQSSSSQPKKVk{}wqpruvvuv{}|~~tbTOONRY_cefffedb`^\\[ZWVY`ilf\SJEDGIHHHHHIIMK;((8EE8*%')-26;@CCCDDDEDB=84338DKNPQOLJHGGEDCB@?>>>>>>@CEEEEEEECCBA>;764446762/--,,+**+07>?>AJQSRRSTTUY`fn}ylilmmkhbWQNKHHHGHLV^_ZSNLIC=98:?FJKKLMNOPRSTUVWVSTXZVMA6,&"#'*,./-&"!!!! !$$! ! a`^ZUPKGCB@><:99;>AEILORTVWZ^cfjoqstuutsu|{ncadffcbba^]^`bccb`__]YUQOOPQPNMLKKILZmtqnory}xg\UPPU[aeffgfdb_\ZYYWUW^fnoe[RIEEHJJJJJJJILH8%$3><1(&(+/48=ACCCCCBBB?;7434:FMOPPOMJGFEDBA@?>======>@AAAAAA?<;<==<;96547:82+%$##"!!#-;IQQPSTSQRRSTTYkrxxlikmmljf_YTOKJKJMS\cc^VQMIC<878=DIIKLMNOQSSTUVVUSTXWQF;4+&"#'*,('-52' !$# !$$ !! ZYWSNHC@==<;:999;>AFKPTW[\^`chknpstvwvvuuxytlhjkhddddccb__acddcc`]XRONNNMJFB@@ABIZikjntx~
saTMMPV_deeffda^[YYYYZ_gmpmcZQIEEIKLKKJJIIG>1%#(,*&$&(,16:>ABBA@@??=:74335;EKKKKIHFDBA@?=<<;;;;;;;<<======;779;<==<:759><3)"
$4HTURQQQPQRRSSXsy~
wkhjklkkid_YRONORW]dhhbZTOKFA=;;=@CDFIKLOSUUUTTTSQRSNE<63,'##&**'*7D?. $%"!#%$!!""! SRPLGB=;::::::::;=BGNSX\_abehloqrsuvwwvtsstrpnonhfgfeefea_`abcdd`[UPLLLMHC=73358DXfhkv~~
{cRJIKR\bccdec`^[YZ\^bjrsohaZQIEFILLKKJIHGA4/.+%!!$')-27<?AA@?>=<;8531136:@CCBB@??>==;:98788888889;<<<<<<;::<=>>==<97<A?5*#""!! -AMONNPPPPQRRSVu{xlghijjjkkga[YZ]aehlmke_XQMKHEB@?@ADGJNPSVWVUTSRQOOLC93340)$#&(('+5=9-#!%&%#$&&"!##! LKIFB>:98999999:;=BGNTY^cfgiloqrttvvwwvurrsssrpommmkhgfgddba`aaa_[UOLLNOG at 7.**-0AVdipfRGFHNY`cedec`][ZZ`ekrxume^YQIEFIKKIIJKID?/683( %%&*.27=AA@>=;:9741/-/37;???>==<<<<<;:9889999999:<@BBCCCCCEFFFCBBD?;BIF8*''&%#"" !,=HKLNPQPPRQPRXsz
}jeegiijkmlifehkmmnppnga[SPPMKHEDDGIMPTVXYXWVTROLLLF;1.241*%%'*)&%(**(%%&$&%#%$! "#! ! !DCB@=;:88888999:<>@ELTZagkmoqrssuvvwwwwvttsttsrpnnnmkiiigfecbaaa^[UPOPSTME=50/05BTbgr¥|dTIHIMU]dgedcb`^]`cglpqnhaZUOJGGIJJHHJMKDCA93/'!%%'-148>BA?>;96531.,+-3;@ABBAA at AA@@???>??===<<;
;<BIPVUTSVUVVVVWWXTYZVXS?-')'%#""!$.=GLLNRSONRPKPbsz~
zjdcdhjiillkklmomlmqrnh`ZUTSRPOMLKLNPTUXYXVTUVRKDEGB5-/230+&&,.,(&%%%&&&!%1-"$! !!""""! A@?=<;:99999999:;=@ELT\bjmorssstvwwwwwwwuuutssrqommllkkjhgfedbba]ZWTTVXYVSPLHDA at GU`fp~
na[SONPTZadedddddddbbbbcdebYSNJHHJKKIHJLKHF?1%##!$)*,047;@BB@>;853220-,/6>CEEEEEEEEDDDDDDDCA??>>==?HR\bcaabdddddddbaba`b]H1%%$""!!#)3?HLLNQRMLQOKSeuz}znfcdgjiiijkkklljijnpmf_YVUUTSRQPOOPRTUWWWUSTUQIA at EA4-142/)$'.20,+++*)(()3F=)' ! !!"""! @??=<;::;;;;;;;;;<@EMW_ejnprttttvwwwwwwwvvuutssrponnmllljihgfdca[YYZZ[\[[]bcaZRLMW_cm{|yxwvuutspqusgZ\b^YVTUY^addfgiklkgaZUTVZZUPMJJKMNMMKHGJQTG/$%%*0115;@AA@?=;864321004:@DFFFFFFFFGGGGGGGEB??>>==?IT^dfeefgggggggfegfeieQ8*(()*+,-29AGIJMPOKKOPPZivy|
zqkeceijijjjjjiihfhlnkd\XVWVVVUUTQQRSTUVVVTSRRMGA?D at 4.263,&"&/5312210/.-($88.2+!%%###""! @@?>=<<==>>>>>>=<<@FOYaglnqstutuvwwwwwwwwvvuuttrqpponnmmlkjihfea[Y\^__^\[^dhf`XRRX]_ivztnmmllkjhiosgQGTcc^ZXWZ^afhijkmnnlg_VPMMNNMLKKLNOPPMHFM]fX;%#)(%(-006=BA?>>=;8
65310137<ADDDDDDDDEEFFFFFFEA??>>===DMW^aabccccccccdehggkiW?22479:;:;>CEFGLONLMORXdowxz~{wsmebdhjjjjihgffddfjlibZVVWWXXXXWTSSTTUUUUTRPMID??C at 4.262*# &0664466666617OUNPD20)&%$#"! ##" AAA@@??@@AAAAAA@=>BHQZcimortuuuvvwwwwwwwxwwvvuutrrqqpooonnmkjihc\[^aa_\ZZ\_a`]ZVUXY[esuommmnoopoqyv_D>P`c^[YY\`eikjiihhhihe`YRLJKLLLLNOPPQNJJUiraA)&+*'),05;AB?===<:9763/.15:>ACCCCCCCCDDEEEEEEDA??>>==<>GRZ]^_aaaaaaaaaceddiiYC89<?ABB?>@CDCEJMMOPOT`nuxwx|~|vsqmeacgijjihfecbabejkibZUUVWXYZ[ZWVUUUTTTTSRNIDA?@D at 4.251(!%08865679;<>?¦xgP:6,('&%$#" #%%$!DDDCCCCCDDDDDDDC at ADJR[cinprtvvvvwwwwwwwwxxxwvvuusssrqqppppomlkjfa_``_[XWX[[\[ZYWVWUVbqrmorstuuvvuwlP;>R`b^[YZ]aeiigeca_^]`deb\TOLLMMMNNOPPMMSar{\A,(*+,/4<GLIC>=<=<:9763005:?BDDDCCCCCCCDDDDDDDCA??>>==;>FRZ^_accccccccb````giZD88;>?><::>ACBCGJLPQMScsxwvwy{xrnlicacghhiigeb`^^bfjlibZUSTUWY[\\ZXWVUTSSRSQLD?>?BFB4-03/'!%0886668:<=?@¹¼jR=.0,(''&&&%&'''&%#"FFFGGGGGFFFFFFFEDDFKR[bhnqsuvwwvwwwwwwwxxyxxwvvvuttssrqqrqponllifdb_[VRQSVXYXVSQSTRS`oqlnrqqppomhcR:3E[de`\YXZ^acca_]ZYXX\`ba\VQNMNN
NMLMNMLQ^my{dK80-*.7BQbdVG?==<;:987524;AFIJJHHHHHHHHGGGGGGGEB??>>==;<DPY]_bdccccccca_^]^fi[F88:<;8424:?BBBEGHNOINbrvwuvxyvnjfc`adgfghhfc`][\bgkmjc[URRSVXZ\][ZYWUTRRQSQJA<<?DID5-/1-'! %07878:::::::o{gH=/#((''((()+-.+)'%%%KJIIIIJIHGGGGGGFFGIMS[bgnqsuwwwvwwwwwwwxxyxxwvvvuuttsrrrsrqppnnmigd`[WTRKLPRRNIGNPMMYjlimomic]\[PL;)0Ndffa]YXXZ\\^__]YVUVZ^^[UPLMMNONMLMNKJRcs{{q_L<0+3=Resr`MA<<;;:987637 at FKMMMLKKKKKKKJJJJJIIGC@@??==;9?JTZ]_````````_]_^_eh[G96BA872,.4:@CEEEDLLCH^ortuvxxsjd_]^adfeehheb^\[]dilmjc\WPPRTWZ\][ZYXVTSRQPNF=:;>EJG9.,/.'" $.467;==;95402JPIJ4""%&&&')+.11.*(&&&RPNKIIJKJJIIHGGHIJLOV\cioqtvwxwwxxxxxxxxwwwwwwwwvuuttssrrrrrqqpolihfc_\WNKKMLIB at EGDFNV^eknjaTI?8::.!2Xlfda^[YYYWY\bb^VNHKOVXUNIGIKLLLMMNMFBIZjrttocRCAQflptqeSC:8::;:87327AILLMMMMMMMMMMKKLLLKJGDBA@?>><:=ENW]^^_______^]_`_dfXG;3VQ7A>4236=DHHCCLJ<B\nnqrtsoh`WUV\_bcdfgeb^]^_dgklkhb\VONQSVY[[YXXYWUTROLE=87:=CJK at 2*++%! "(/469<=<731.)z·W0#&&%$$&*.0210.+)('WUQMKJKLLMLLKJJJKKMQX_fkortvwxxwxxxxxxxxwwwwwwwwvuuttssrrrrrrrrqmlljhdb_[WTROJB<<=?CHNS[fjfZK=5104+
"5\rlea^\ZZZZ\_cbZOD>>CKLJECCFGHIJKKLI?68FWagpuuoggpvsomjcTB869::986317BIKKLMMMMMMMMMLLMMMKJGEDCA@?><<=BLV]^^^______^]`a`cdVG>7hbBRUME@=>DHHFIOH9A^ooookf`ZVRQSY^`acddb_]^`dgjkjhe`[VQPRTVY[ZWWXXWVTSOH?7359=BINF7+))%! "&+1568;95222Sǧ`3,-)$##&+033331/-*(][WTQONOOPONNMMLKLNRYahmpruwxxxxxxxxxxxxwwwwwwwwvuuttssrsssssssrqpomjfbab`]ZXRI?76;@EHJQ[`\QC6/--/(#7]xxmea]\[\]_``^XOEAAEFC>;<?BDFGHHGGA5(&0>IMRZgszzwsmjif_Q at 65899875228CIKKLMMMMMMMMMLLMMMKJHEDCBA?>=<=AKU\^^^______^]`a`cdVF?<rmK`kibWLDCFHJMMB8Ebqmid[SMLNOQSW[^`aa_^]]`dhjihgea]ZVRRSUWYZYWVWWVUSRNF<3/28=AHNJ=0(%"!!"&*/235641046M}}F'$((%%&).243210.,)'gec_[XVTRPPOONNMLLNSYaglqsuwyyyyxxxxxxxxwwwwwwwwvuuttsssstttttttssrplhea^[ZYYVOD6259=BEKUXTI<1,,--((9Zzoje`]\]^^]]]\WPLMMJC;8:>@BEFGFD at 6*!#+20,2F^qvogedb_YM=4467875413:DJLKKLMMMMMMMMLLMMMKJHEEDCA@?>=<@IS[^^_______^]`a`cdVE;:qkH`rxujYJDEILKF<8I`g_UOIEEHLORRSW\__]ZYZ]afjkgdb`]ZWUTSTUVWXXUTUVUSRPLD90-08<AFMMD5(" ""#&)-/1220-/541CO@*"#$&&'),0451//.,)&$wusojfb]WSSRRQQPOOQTZaglqtvxzzzyxxxxxxxxwwwwwwwwvuuttsssstttttttuu
tsplie]XVVUQJB95448?FMSTPF:1-/0.+.:Rtyqjb^]]__\[\\XPIHIGB=<?BBCEFEB?7+# !""#4Mfqnfa^[XSH:2256654214;EKLKKLMMMMMMMMLLMMMKJHFFEDBA@>=<?GQZ^^_______^]`a`cdVE;7ldB\r{{raOEEKOLD<:DOMB;<>CHMPSSPOSY]]YUVX[`ehhd`][XVUTTTTTUUUTSSTTSRPOIB80-17<?DJNI<* "#$&(*,.01/-/5841,(,31*()*,/3563221/,*(
|vqkb^^]\\[ZYWXZ^dimrtwyz{zzxxxxxxxxwwwwwwwwvuuttssstuuuuuuuvvvuspnke`\XTMD?=<87;BKQSRMC81/33-,27Bbyoe^\\^`]YYYQD96:>?>?CEBACDA<6-#!"! !, at Udie]XURMD81144542115=GLMKKLMMMMMMMMLLMMMKJHGFFDCBA@=<>EOY]________^]`a`cdVG>7g^@]sz|teTGCGNNG>8882.07?GNRTVTOKOW\[VSTVZ]`cc_\YVTSSSSSRRQQQPQRRSRPOLGA93137;?AFLMB."#$%&&'),021/04;=3&$-2+%(-.024567887520.
yqoonmmljecbceinqsuwz{{{zyxxxxxxxwwwwwwwwvuuttsssuvvvvvvvuuvvvtrqmid`\UKEBBABEKPSQOI at 61043++2//Lsth_[Z\^[Y[[SB406>CB@??>>@?:3+% !#*5DS]_YSPMIA6/033431006>HMMLKLMMMMMMMMLLMMMKJHHGFEDBA@><=DNX]________^]`a`cdVH?4^W?`uyzuiXH??EHA7/++.4=BGLPSTUUOILU[YURSUXZ[\\[YVRQPQRRQPONMMMOQQRQONKD@;8668;=>AJOG3$!#%%&%%&,256313772++,*'(-1234444677641.-¤£¡
~~}}|{zxrnkjlostuvxzz{zzy
yyyyyyywwwwwwwwvuuttsssuvvvvvvvuuvwwvusoligeaZTKJLMOQRRQMF=4/032++1,'<j}naXY\\VWcc]O:8?EGD?::9::72+# !#&)/6 at KW[VOLID<2,033321/0:BIMMLKLNNNNNNNNMMMMMLKJIHGFEDCBA>>DMV\________^^_`adcTF=2RM=`ww{yn[F97;;4+$#,:GMNNOPQQSSOIIV^]TQSVWWUTTXWVSRPOOPOONMLJJLPSSQMJGC?=;:99;=>AJOJ9+#$%%'&$%,1553112469;969:745420....//.,)'®®«¨¢ysopsuvvwxxyyyyyyyyyyyyxxxxxxxxvuuttssssttuvvwvvvvvvvvtqnmkifd_XVVVVTSTSND81/021,-/.+12ex
gVU^\SY~´´yH;>?>;866441-(# ""&)06<EOSRMJE>6.,,.//0016BHJKKKKLMNNNNNNMKJKKKJJIGGFFECDDA?>AIS[^_______`_^^afbQC<7FD?_xwtqeQ=1.0/*$#(4DNSQPOOOPNOQJFXrkTPUXYUQLKNPQQOLHFIKMNMKIGINTTMFB@@??>=<<<>@DKPK at 4(%#%'(&&)-//////149;:9;:8763-'%#%&(**)'%¶µ³°«¦¢xssuvvwxxxxxxyyzzzzzzzxxxxxxxxvuuttssssttuvvwwwwwwwwwuronkigfd_][YWUSTUOC70/120.////02CbnXQVXTdÃÂU642/.--/0/+'$! !!!#)05:AJPPMIB;4/)"!$(-15<EJJJJJJJJJJJJJJIFEEEEEEDCBAA@??>:88=FQZ^`______``]]bgaO?9:DCB`xmaVH;2-*)''*.7 at IOPPPPPPPOORKCWsmUOW\^ZTMGAADFEA<<BGJLLKIHJOROG@=>???>>==<>@ELOLD:-&#$&(&%'))**+,-024566655772*# !#&)))'%
¾¾¼¹µ±ª¦¥¥¤¢}wvwwwxyyyyyyyzzzzzzzzxxxxxxxxvuuttssssttuvvwwwwwwwwwvsqonljigeb`]ZWUUUOC70/121////./(,Ek~wcSLJHV{zO2-+)''')*)'$"! !!!!%*058=DFA;5/)$!#(.37=EIIIIIIJKLLLLLLLLLLLLLLKGFFEDDCDGHHJNT[_`______``]]bgaO?7:FEDas]F6)%)-*%%+6 at ILMNOPPPPPPPPSI@TrnXSZ`ba[SLGFFFEDBACEHKLLJKOPLD=9;>@??>>==<<>BINMG=1($"%&&%%&'(())+.02343323550)" !#&(('%$ÃÃÂÀ½¹¶´±±°®«§¤ {yyxxyzzzzzzzzzzzzzzzxxxxxxxxvuuttssssttuvvwwxxxxxxxwtsrpomlkiheb^ZXXUOC70/121//..--(!/Oo~v^ME@=IZ]L:0.-+**+*&$"! !!!!!"&,1569=CIHD?;87:@DEGHJKMQRRRRRRRRRRRRRRRQQQQQQQOLJJIHHGFEEFGJPX^_______``]]bgaO>9?KHE_iK2(! $)++/7BLRRPNPQQQQQQQPRG?UwxaX[_cc^VSUSKDACHIGFJMOONOPMB834:>@??>>==<;<?FKMIA5+$!"$%%%''(()*+,./110//033/(" "%''%#!ÅÅÅÃÁ¾»¹¸¸¶³°«§£
}{zyyyzzzzzzzzzzzzzzzxxxxxxxxvuuttssssttuvvwxxyyyyyyxvutsrqppnmjfb_\[WOC70/121/..-,+)''8Z|lVNI@>@?6//0/.-./,$ !"!!!"'-36679>CDB@???@A@@@???><;;;;;;953333331.,,,,,,,,,++*))+/368<FT^`______``]]bgaO?=FPHC[^9&&'$!#*3?FKPRRPPQRRRRRRQOPE>Xp_\\_a]UTXR at 1,0:BHJNQSSRQME8/-29>@??>>==<<;=BILKE8.$"$
&'()**++,-.///.-,.01-&! !$%%#!ÅÅÆÅÃÁ¿½¼»¹¶±¬¨£
~|{{zz{{{{{{{zzzzzzzzxxxxxxxxvuuttssssttuvvwxyzzzzzzyxwvvuttsqomjgdb_XOC70/131/.-,+*+,',Im~s^QMLLJA4,+-+**+,*$ !"!!!"(.58878710369:::9:;<>?@ABCCCCCCCCCCCCCCCDDDDDDDFIKJJIHHLTWRICGT^a______``]]bgaO@>IRFAYX0&+)$%.<KPOOPPQRRSSSSSSROOC=Y
{h_YY\[TQ]S?-&*4>INQTUTSND9.),3:>@??>>====<<?FJJG<0$ #%())**+,--.///-,+,./,% !#$#!ÆÇÇÇÆÄÃÁÀ¿¼¸³¨£~|||{||||||||zzzzzzzzxxxxxxxxvuuttssssttuvvwxyzzzzzzzyyxxwwwusqomkhgcZOC70/131/.-+*))*(-?WimfRLLLKC7.))'''()($! !"!!!"(/6::89;?DLTY[Z[_bcehjknqsssssstwxxxxxxz|~~~~~~zthUGGS^a______``]]bgaO?=HPC?[Y/ &*-28?GNQPPPQRRSSSSSSSRQOB:W
pdYVYZUSd^OB;;@FKORTTRPH9-&'.7;>???>>==>>=;>CHIG?2%#%&&'(())+.000/-,**-.*$!"#" ÆÇÈÈÈÆÅÄÃÁ¾º´®¨¢|||}|||||||||zzzzzzzzxxxxxxxxvvuttssrsstuvwxxzzzzzzzzyyyyxxxwusrpnlkg\QE921220..,+*)'')09DR`f[MEBDD@;.,,+*++(%"! !"!!!")/6:;::;<BLXaedbb`abbded^]]]]]][XWXXYZZYXWWWWWWUUTSRPPPTRPLA6<P\`_______`]]bg`N>:FM@@\\8(*-6BLPPOPPQRRSSSSSSSSSSRO at 8Uvj[UXZTQbaYPLLOOQPOPRO
I at -%#'/8<>@@??>==>?=<=ADED?3&!#$##$%%&(-///.-+*)**'# "#" ÆÆÆÆÆÆÅÆĽºµ®¦{{}}~}}}}}}}}{{{{{{{zyxxwwwwvwvvtsrqqqrstvwxyz{{{{{{zyxxxxxxywvusqomkbWJ?8420.-,,,+++(*,.2:CFH at 78?ED;37;8760'""!!!!!""! %,169:<<:8;AB@:535:<==;;9:9999999<:87521/+))))))'# #'+)&'37@=/8R[_]]]]]]__]]bf_N<9FK at E[]I76:BLSUTRQRSSSSSSSSSSSSSQL>8S}~taTTYQITUOHDGPZUNKNRN?.""'07<?@@@??>>===<>????=5) ! !#$%&'*++++**(&%&$! !"##! ÅÅÅÅÅÅÅÆÄÁ¼¸´£z{}~~}}}}}}}}{{{{{{{{yxxxwwwwvvvtsrqppprsuwxy{{{{{{{zyxxxxxxxyxwuspomeZNC=83/-,,,,,,,*('&'+/32-)-6<936AIHEA4' !!!!!!""!!%-258:<<;:99:<>@>:8;=@AA@>=========>@ABCDEEEEEEEHOSUWYZXR83BC2;V\]]]]]]]^_^^be^N?;HKCGX[NDDHLOQSSSSSSSSSSSSSSSSSSQK=7Qy
|gTPTPGA>80+.8BJJKRWP;)#)07<@AA@@?>>=<<=>>=<=<8/& !""$%'()*))))))))'&%$"! !"##"! ÅÅÅÅÅÅÅÅÄÀ»·²ª
~z|}~}}}}}}}}}{{{{{{{{zzzyxwwwvvusrqpomnprtvwyz{{{{{{{yyyyyyyyyxwusrpng]RHA;50,,,,,,,--,($"#$&'$#(/2/-9JUUQJ9)!""""""#"!"'/369;<<=><86:AJQXZ\_adeiqttttttuxz{|~~|zwspml76EF5=V\]]]]]]]^`^^ac]OCAKMEHUWOMOQRSSRRRSSSSSSSSSSSS
SSSPL>5LsnUHIIE?<7/)(-4=FR]_R:'$*18=?AA@@?>>=<<=>>=<=>=71+(%%%'()+,--*)))))))))(&%$#" !"##"! ÅÅÅÅÅÅÅž¹´¯§}{|~}|}}}}}}}}{{{{{{{{{{zyxwvutssqponlkkmortvxz{{{{{{{zzzzzzzzyxwvtsrpiaVNF?60-,,,,,,.11-)&%$&)().4511>PYWSL=-#########!!#(157:;<<=?=97:AIS_bbbcdec\YYYYYYYYYXVUTSRPPPPPPPRTVVTQQTQ>8HI7=UZ]]]]]]]^_^]__ZPGFMNHJRSNPRTTTSRRRSSSSSSSSSSSSSSROL>3Dk
vZD=;;>@=82035<I]idP5#%,39=?AA@@?>>=<<=>>=<=?@>;71,)))*+,-.-*))))))))('&%#"!!!"##"! ÅÅÅÅÅÅÅÄÁ¼¶±¬£|{}~}||}}}}}}}{{{{{{{{{zyxvutrqpomlkjighjmpsuwz{{{{{{{zzzzzzzzyxxvutsrkd\TLC81,,,,,,,-//-+*)(*./158857CQUQLI>/%#######"!"%*279;<<<<==<;<>@AA?<9878;@BBBBBB@;8764320/......*""'),4?C?:JK7=SX\]]]]]]]]\[[ZVOJJNOKLPQNMOQSSSSRSSSSSSSSSSSSSSSRNM?0=cgL=401552.-14?RipbG- &.5:=?AA@@?>>=<<=>>=<<>@BA>930---,,,,+*)))))))'&&$#"! !"##"! ÅÅÅÅÅÅÅÄ¿º´¯© {{}~}||}}}}}}}{{{{{{{{yxwusqpnlkjigfeedegjnqsvz{{{{{{{{{{{{{{{yxxwvuutnhaZRG:1,,,,,,,+)()))))*-/023326AMPKGE=/&$$$$$$$"! #',48:<<<<;<<=>=;888853468730000000//02345688888889=?>946?C?:JK7;OU[]]]]]]\[YXV
SPMKLNNMNOONMMPRSSSRSSSSSSSSSSSSSSSQNM at -5[|oVE8-*,,*(*/5BXmmV9% (07;>?@A@@?>>=<<=>>=<;;=@BA>:7321/-+*)))))))))'&%$#! !"##"! ÅÅÅÅÅÅÅľ¸²§~{{~}{|}}}}}}}{{{{{{{zxvuspnlkhffdcbaaaceimpsvy{{{{{{{|||||||{yxxwwwvupke^VJ<2,,,,,,,*('()))()*,,+*+-1;GNLIF;-%%%%%%%$#! !$(-6:;<=<<<<==<<:9;@CDGMU]cghhhhhhjmoprstuwyzzzzzzwqldTC=BD=9IJ58LRZ]]]]]][XVURNKKLLLMOPOPQPQRSTSRRRSSSSSSSSSSSSSSQMN at +0Uy
}hVJ>3..-*(*17CWhbF+ )18<>?@A@@?>>=<<=>>=<:79=@A@>=<:840-*)))))))))))(&%$#" !"##"! ÆÆÅÅÅÄľ¹²«£}{|~}||}}}}}}}{{{{{{{zxvtqnkigdcb``^^^^`cgloruxz{{|||{|||||||{yxxxwwwvrmhbZN at 6/.-...-+*+,..-+*(**))-01:DLNOJ;+%%&&&&%$$" "&+16:;<=<<<=>=<=>@?:8;@HWfjgcccbbaa`a_\[ZYXYYYYXYXZ_aWM=8BF=8IJ57HKX\]^\Z\^UQQNKIJLMMMPPOPRTTUUTSRRRSSSSSSSSSSSSSSQNNA,,Lr
|kVKF>3.0/*'*04CYcS7# *28<=>@A@@???>==>>>==;77;>@AAA@?=840,+))))))()**)('%%#!!"#$#"!ÆÆÆÅÃÃÂÁ¾¹±©
~}}~~}}}}}}}}}}|{{zzyyxwurojgda^]\\[[ZYZ\_dinrtvxy{||||zzzzzzzzxxxxxxxxtpkg`UH?4200220---0210.*,1547?BCDEGLQL;,$&'''&%%$" "*0689:;;;;<<<=?ACED><<=@?<<<<=>ADHFFCDECA?=A@?
=<9:883IL84BC=7IK65AEQZ]\ZYZWOLLKJKKMOONOPOQRTTTTTSRRSSSSSSSSSSSSSSSRPNA.)@g|hVQPD2-6;41555KacF(!!+48:;>?@AAAAAA??>??>=<99:<=?ABA@?=963/*()(('(((('&%##" !#$$$#"ÇÆÆÄÃÂÁÀ½¹±§
~~~~~~~}}}}}}}}|{{zzyyxvtqlgc_\XWWWXXXXXZ^bglqsuvy{|}||zzzzzzzzxxxxxxxxuqmicYNC9412442000101002;EJINWZUOHEHNJ:+$&&&&%$$#" #+379899:;;;;;<>ABDEDBA@?@A?979;>BFHHHHHGDB?9654210132EM83CD=7IK74>?KYZUY`\OIJJKKLMNPQOOOOQRRSSSSSSSSSSSSSSSSSSSSSSSOK?.':azqojU;0=HFBB;3TifC%"".69:<?ABBBBBB@?>>>>===<;:9:=@ABBBA?<:5,(('''))('&%$""! !#$%%$#ÆÆÅÄÂÁÀ¿¼·¯¥~~~~~~~}}}}}}}}|{{zzyyxusnic]YVSRSTUVWXZ[]aejortvxz||||zzzzzzzzxxxxxxxxvrnke]QG;5224643430./26=MY]\_hjbUKEGKG:-%%%$$#""!! !%,37889::;;<<<<=>?@ADDCCCDFD=:<?CHLNOOPONLJF?<<:987752EM83CD<7HK64><ETZYaiZGEKKLMMNOPQOOOOQRRSSSSSSSSSSSSSSSSSSSSSSRMH<,';b}
gG:FUWSLA7^oiG'!%08<=>BEFEDCBA@=<<<===>=;867:>AAABBA?>91,)'&')*)'&%$""! !#$%%$#ÆÅÄÃÂÀ¿¾ºµ£~~~~~~~~}}}}}}}}|{{zzyywtqlf_YURQQSTVXYZ[[\^bglpsuxz{{{{zzzzzzzzxxxxxxxxwtpmi`VK>732566553/.18 at HU`dbellaTJFGKI at 4)%$"! !$(.4799::;<<=?@
@@???@BCBCDEGGDCCEHKNONNNNLJHHHHHGFEEA82EM83CD<6GJ53=9>H[nqbNFHLMMNOOPPQOOOOQRRSSSSSSSSSSSSSSSSSSSSSSRMF:,*@g|qVHOZ^YRIDivpO- ! "(4<?@BEHJHGECB@=<<===>?@>:669=?==>?@?>=960+('()('&%$""! !#$%%$#ÅÄÄÂÁÀ¿½¸³«¡~~~~~~~~}}}}}}}}|{{zzyywtpke_YTRSUVXZ[\]]\\\_dimrtwyz{zzzzzzzzzzxxxxxxxxxurpleZPC;53566521139BKQWagfhkg[NGFINNI>.'$! $(-268;<<==>?ADFEEDDCCBBABCDFHGFEDDEGGGFFFEB at AEGGFFEEA92EM83CD;5GI52<78=^~TAKONNOPPQQQQOOOOQRRSSSSSSSSSSSSSSSSSSSSSSSNG:-/Gm
~kZWYYUQRZry[7# "%,8 at CDFIKLKIGFDC?>??@ABCDB>;:;>?@@ACDCBDDB<5/+((('&%$""! !#$%%$#ÄÄÃÂÀ¿¾¼¶±©}~~~~~~~}}}}}}}}|{{zzyywtplga[WVXYZ[\]^_^][Z\agkqtvxzzzyzzzzzzzzxxxxxxxxxvtroi_UI at 844553137=DKRTZenopofUFBEKPPKA2)%! !! "'.379;>??@AABDHIIIHHHGECCBCDEFECA?>>>?ABBB@><:9888888752EM83CD:4FI42<65<^vL at OROPPQRRRQQOOOOQRRSSSSSSSSSSSSSSSSSSSSSSSNF8.2Lq~i[TROP[l}iC(!#'0;CFHIKMMLKJIHFCBCEFGHHIHFCB@@BFIKLLLKLMLGA:3.+('&%$""! !#$%%$#ÄÃÂÁÀ¾¾»µ¯§}}~~~~~~~}}}}}}}}|{{zzyywtqnid_\[Z[\\\\]^_^ZYZ_ejpsvxyyyyzzzzzzzzxxxxxxxyxwutrlbYNE;5443238AIORRQYiuyxtfQ@
>DKNLF>2,'# """$+28;<>ABCCDEEGIJJJJKKKIHGFEFGFECA@??@ADEFEDB@;3000001242EM83CD:4EH31;45F[a[RMMNPQQRSSSRQOOOOQRRSSSSSSSSSSSSSSSSSSSSSSSLB4+2Mr}n]SQORbwvN-!$)2>FIJLNMLLLLLLJHGIJLMNNNNNMJGCDKOPQQONNPQOLF>71*'&%$""! !#$%%$#ÄÃÂÁ¿¾½»´®§|}~~~~~~~}}}}}}}}|{{zzyywurokgb`^\\\[[[[\_^ZXY^dipsuwyyyyzzzzzzzzxxxxxxxyxwvusmd\QG=633226>HRVTPMWix}|udN==DJKG?82.(#!!###&-5;>?@BDEEFGGHHHIJJKLMMMKIHHHHGFEEEGHIKKLKJHF at 6333344542EM83CE84EH31;26RWAB\[FLQQRSSTSRQOOOOQRRSSSSSSSSSSSSSSSSSSSSSSRJ?1)1Mryrj^TSRTf|}U0!#*4?GKLMNMLLLMMNMKKLNOQRRPQSSPKEEJNOOOMKKNQSSNG?6,'&%$""! !#$%%$#
¡¢¡ ¡¡
}
{yz~pppppppomllllllmoqsvy|~zxxxxxxxwvspmigfeffffffeddegiklosuvwxyzz{zzxwvutsrstuvwyz{{{{{{xqnnnnnnrz~~~~~~}yxxxxxxxvvvvvvvusrrrrrrtvxxxxxxyyzzzzzz|~~~}}~~}}}}~
~
||~ppppppppooooooooqrtvy|~}zxxxxxxxxvtpmjgfgggggggfeefgiklnrtuvxyzz{zzxwvutsrstuvwyz{{{{{{ysqqqqqqt{~~~~~~}yxxxxxxxvvvvvvvusrrrrrrtvxxxxxxyz{{{{{{|~~~~}}}~~}||}}
pppppppqrsssssssrsuwy{}}zyyyyyyyywuqnkhghhhhhhhggghijkknqtuvwxyzzzzxwvutsrstuvwyz{{{{{{zwvvvvvvx|~~~~~~}yxxxxxxxvvvvvvvutssssssuwyyyyyyz|}}}}}}}}|}}}}}~~}||{|}~
~~
~ppppppprtvvvvvvvttvwyz{{{zzzzzzzzxvrolihiiiiiiiiiijjjkkmpssuvwxyzzzxwvutsrstuvwyz{{{{{{{zzzzzzz{}~~~~~~}yxxxxxxxvvvvvvvvtttttttvxzzzzzz{|}}}}}}|{z{{|}}~~}|{zz{|}~
~
~~pppppppruwwwwwwwvvwwxyz{{|||||||{ywtpmkjijjjjjjkklllkkkmoqrsuvwxzzzxwvutsrstuvwyz{{{{{{||}}}}}}}~~~~~~~}yxxxxxxxvvvvvvvvuuuuuuuwz|||||||{{{{{{{zxwxz{}~~~}|{zyyzz|}~
~~~~~~
~}ppppppprtvvvvvvwwxxxxxxy|}}}}}}}|zxuqnlkjkkkkkklnonmlkjlnpqrtuuwzzzxwvutsrstuvwyz{{{{{{||}}}}}}}~~~~~~~}yxxxxxxxvvvvvvvvvvvvvvvx{}}}}}}{xvvvvvvuuuvx{}~~}}|zyyxxxyz|}~
¡
~~~~~~
}}pppppppqsttttttuxyyxxwwy|~~~~~~~}{yvromlkllllllnpqpnmkjkmpprstuwyzzxwvutsrstuvwyz{{{{{{{{{{{{{{|}~~~~~~}yxxxxxxxvvvvvvvvwwwwwwwy|~~~~~~{tqqqqqqqrsuwz}~}|{zyxwwxyz{|}~
¡
~~~~~~
qqppoonopqqqqqqrvwwwxwwy|~~~~~~~}{xuqnkjkkkkkkkmooomljjjlnoqrstwyyywutsrrrstvwxzz{{{{{{{zzz{{{{|}~~~~~~}zyyyyyyyvvvvvvvwwxxxxyyz{}~~~}|xqmmmmmmmoqsux{}}}|{zyxwwxxyyzz{|
srqonlkjlllllllmqrstvxy{}~~~~~~}|{wsojhghiiiiiiijkjjiihiklmoqsuvwwvtrpooqrsuvxyzzzzzzzzzzz{{|}~~~~~~~~}{zzzzzzywvvvvvvvvwxyzz{{{|}~|yvqljjjjjjjlmoruwxz||{zyxwxz{zzyyxz}~~~~~~~
tsqomkiijkkkkkklnpqsvxz|}~~~~~~}|zvrmifeghhhhhhhhhhhhhhhjkloqsuwwwusqommprsuvxyyzzzzzzzzzz{|}~~~~~~~}|{{{{{{zwvvvvvvvvwxyz{|{{{}}{wsojiiiiiiiklnpsuvx{|{zyxwx{|{zy
xwy|~~~~~~~¡¡
tsqomkiijkkkkkklnpqsvxz{}}}}}}}}{zvrmifeghhhhhhhhhhhhhhhjkloqsuwxxvtrpnnqrstuvwxz{{{{{{{zz{|}~~~~~~~}|{{{{{{zwvvvvvvvvwxyz{|{{{}}zvqmjiiiiiiiklnpsuvx{|{zyxwx{|{zyxwy|~~~~~~~¢£ £¤¤¤¤¤¤¢
tsqomkiijkkkkkklnpqsvxz{||||||||{zvrmifeghhhhhhhhhhhhhhhjkloqsuwyywusqoorssstttvxzzzzzzzzz{|}~~~~~~~}|{{{{{{zwvvvvvvvvwxyz{||{|}|ytokiiiiiiiiklnpsuvx{|{zyxwx{|{zyxwy|~~~~~~~
£¤¡¡£¥¥¥¥¥¥£¡
tsqomkiijkkkkkklnpqsvxz{{{{{{{{{{zvrmifeghhhhhhhhhhhhhhhjkloqsuwzzyvtrpprsssrrrsuwwwwwwxyz{|}~~~~~~~}|{{{{{{zwvvvvvvvvwxyz{||||}{
xrlihiiiiiiiklnpsuvx{|{zyxwx{|{zyxwy|~~~~~~~
¤¥¢ £¤¤¤¤¤¤£
tsqomkiijkkkkkklnpqsvxzzzyyyyyyzzzvrmifeghhhhhhhhhhhhhhhjkloqsuxz{zwusqqstsrqpoppqqqqqqsxz{|}~~~~~~~}|{{{{{{zwvvvvvvvvwxyz{|||}}{vpiggiiiiiiiklnpsuvx{|{zyxwx{|{zyxwy|~~~~~~~
¥§¢ ¡¢¢¢¢¢¢¡
tsqomkiijkkkkkklnpqsvxzzzyyyyyyzzzvrmifeghhhhhhhhhhhhhhhjkloqsux{|{xvtrrttsqpnmmlllllllpvz{|}~~~~~~~}|{{{{{{zwvvvvvvvvwxyz{||}}}zungegiiiiiiiklnpsuvx{|{zyxwx{|{zyxwy|~~~~~~~¤§£¡¡¡¡¡¡¡
~
srqonlkklmmmmmmmnpqsuwyyyxxxxxxxyyurnjgfghhhhhhhhhhhhhhhjkloqsux}~{xusrsutromkkjhhiiiijmuy{|}~}~
~~~}|{zzzzzzywvvvvvvvwyyz{|||}}}ztnhfikkkkjjjlmopstuvz{{{zywx{||{zxvw|~~~~~~~¢¤¢ ¡¡¡¡¡¡£¢
ppoonnmnnooooooooopqstuuvvvvvvvwwvtqnkjihhhhhhhhiiiiiiiiklmprtvz~~yurpqsutplihihggghijjntxy{~~{{}}{xwwwwwwwwvvvvvvvxz{||||}~~}{xtplmnponmmlmnppqqrrswy{||zxxz}}}{xtu{~~~~~~~
¢¡ ¡¡¡¡¡¡¢¢
nnnnnnnopqqqqqqpoopqrstuuvvvvvvvvusqolkjhhhhhhhhiiiiiiijlnprtvx|~yspoprutojgghhhghijklotwy{}zz}}zwvvvvvvvvvvvvvvvx{}}}}}}}~}zwtpnopqqonmlmpqqqqqqrux{}}{xxz}~~|xstz~~~~~~~
¡¡¡¡¡¡
mmmmmmmnoppppppooopqrstuuvvvvvvvvusqolkjhhhhhhhhiiiiiiiknqsuwz{~~
xsonortsnjhhijihijklmpsvxz|~~zz}}zwvvvvvvvvvvvvvvvx{}}}}}}}}|zvspmmpqponmlloppppppqux{}}{xxz}~~|xstz~~~~~~~
~jjjjjjjknooooooonopqrstuuvvvvvvvvusqolkjhhhhhhhhiiiiiiikpsuwz|}|wrnmnprqmihikkjijklnnpsuwy{}}zz}}zwvvvvvvvvvvvvvvvx{}}}}}}}|{yurnlmnoonlkkknooooooqtx{}}{xxz}~~|xstz~~~~~~~
hhhhhhhjlnnnnnnnnopqrstuuvvvvvvvvusqolkjhhhhhhhhiiiiiiikpsuwz|}~{vpmlmopplihjlmkkklnopqrtvxz|~}yz}}zwvvvvvvvvvvvvvvvx{}}}}}}}{zwtqmklmnnlkjijmnnnnnnptx{}}{xxz}~~|xstz~~~~~~~
fffffffhjlllllllnopqrstuuvvvvvvvv
usqolkjhhhhhhhhiiiiiiiknqsuwz{}}zuolkkmonkiiknnmllnopqqrstwy{}|yz}}zwvvvvvvvvvvvvvvvx{}}}}}}|{yvspljjlmlkjihikllllllntx{}}{xxz}~~|xstz~~~~~~~
¡
dddddddfjlllllllnopqrstuuvvvvvvvvusqolkjhhhhhhhhiiiiiiijlnprtvxz|ytokjklnmjiiloonmmopqrrqrtvxz|{yz}}zwvvvvvvvvvvvvvvvx{}}}}}}|zxvrokijkllkihhhkllllllntx{}}{xxz}~~|xstz~~~~~~~
¥¤
bbbbbbbdhjjkllmmnppqrsstuvvuuuutsrqpomlljjiiiihihhiiiijjlnnqrtuwxvrnlklmmmjijloomllnopqpqqsuxz{zz{}~}zxuuuvvvvwvvvvvvvw{}}}}}}|xvtqnkjjikjjiihikllllllntxz||{yy{~~|xrrz~~~~~~~ª²³¯¥¡¡ ª¡
~~~
```````aefhikmnppqrrrrsttuttsrqomllmmnoonmmlkjjihhhijkkmooppqqrqponmnnoolkkjjklkihjjklmnpqrtvxz{}~~}}{zwtsttuvwwuuuuuuuwz{{{{{{yurqpnlkihhiijjkllmmmmmmptwyz{{{}}~{vqsz~~~~~~~¡¦¬²·¸±¤¦¥¦®©
~~~}_______`cegikmoqrsssssssttsrqpomihjkmoqqpoonlkkjhhijklmopqqqqqqomllmopqplkkkkkkjhghijklnprstvxy{}~~|{zywtrstuvwwvuuuuuuvyzzzzzzxsqponlljgghijklmmnnnnnnpuwxy{|}~~{vpry~~~~~~~{y|£°º¼¹¸º¸¯ ¢ª¨¢¡©°
~~~}_______`bdfhjmnptuuuuuuusrqponmkhgiknprsqppomllkijklmnoopppppppolllmopqplkkkkkkjihijklmortuvwxxz}~}|{zywsrstuvwwvuuuuuuvyzzzzzzxsqponlljgghijklmmnnnnnnquxyz|}~~{vpry~~~~~~~
~¹ÂÄ¿½¼·¬¨¯¦¤«³®¢
}}~~~~}_______`acegikmpsuuuuuutrponmlkigfhknqsssrqpommlllmnopqqpoooooonlllmopqplkkkkkkkiijklnnqtvwwwxxy|||{yxxvsrstuvwwvuuuuuuvwxxxxxxvsqponlljgghijklmmnnnnnnqvzz{}~{vpry~~~~~~~¥©²¶º½¿¿¼µ© ®µ²ª¨®µ®¡
~||}~~~}________abdfhjlnqrrrrrrqonmlkjigddgknruutsrqponmnnoprssrpnnnnnnmlllmopqplkkkkkkkjkklnoprwyyyxxxy{{{yxwvusrstuvwwvuuuuuuvvwwwwwwvrqponlljgghijklmmnnnnnnqw{|}~{vpry~~~~~~~¶¹¸·µ³²¶½¿»³§§´º·®«±µ«¤¡}}~~~~}________`acegiklnnnnnnnnllkjiggebcfjosvwutsrqpoopqqrtuvtnlllllllkllmopqplkkkkkkkkllnopqty|{zyxwxzzyxwvutsrstuvwwvuuuuuuuvvvvvvvurqponlljgghijklmmnnnnnnqx|}~{vpry~~~~~~~ ¢¥¨«²¹½¼º¹·¶¹¼½¸±§¬¸¾»±®³µ¨¡ª©¦¦§¥£
~~~}_________`bdfhjjjiiiiiijjjihgfedabejotxyvutsrqpqqrstuwwuolllllllkllmopqplkkkkkkklmmopqru|~}{zxwwyyyxvuutrrstuvwwvuuuuuuuuuuuuuutrqponlljgghijklmmnnnnnnqy}~{vpry~~~~~~~£¨«¯³µ·¸¸¸¸º»¼¼¾½»·°¦±»¿»³°´¶¤®®®°¯¬¨¢ ~
~~________`abceghhgffffffgiihggfedaaejpuyzxvusrqpppqtwxxwtmjjjjkkkklmnoppnkjkkklllmnmnopsv|~~|zyxxyzzyxwutrrstuvwwvvvvvvvvuuuuvvwvsqonmklkiiiiiiijklmnnopsx{|~|wqry}}~~~~ ©±µ¸ºº¸¶¶µ·¸º¼½½¼»¶¯¥¸½¼¸´±³°§°´¶µ·¹¸³ª¡
¡¢¡ ||~
_______`abbcddeefffffffgghhhgggeabfkpuyzywutrpnkknu{}zvoifghiijjjkmopnljjiijkllopomklpty|}|{zyxxy{|}|yvsqpqrtuvwwwwwwwwvuuuvvwwvspmjijkmllljigffhjkmprsuvxyz|~}xssw{||}~ «³·º»¹¶µµ¶·¸¹»»¼»º¶¯¤½½º·´²°« ¨°¶¸¸º½½¸
®¤
¢¦§¦¢
zyz
~~_______`bccccccdeffffffgghhhhhhfccgkquyzzxvtrpnkimu{}ztmgefghijjjknppnkihhijkmmoqpmklpux{{{zzzyyz|~~{wsqpqrtuvvwwwwwwwwvvvvuuuurplighkmppnljhgggiknqsvvvuvxz{|}~}xsswz{|}~ª±µ¹º¹·¶µ¶·¸¹»»¼»¹´¬¢»½»¸µ±®§¡©±·¹¸¹¼»·¯¦££ ¥ª®¯®§¨¨~}||~_______`bccccccdeffffffgghhhhhhfddhlpuxzyxvtrpnljnty{wsmgefghijjjknppnkihhijkmmoppnnoruwyyyyzzzzz|~~{wsqpqrtuvvvvvvvvvwwxvtrpoppokhghjmqrqponnmllnprtvvutuvwxyyz{}}{vrrwz{|}~¨¯³·¹¹·¶¶¶·¸¹»»¼º·±© ¹½¼¹µ°ª¢¢ª²¸º¸¸º¹µ¯¨¡¢«²±©¨®³·¸·±¢¯²ª£¤¢
}{{~_______`bccccccdeffffffgghhhhhhgefilptwxyxvtrpnmloswwuqlgefghijjjknppnkihhijkmmnpppqrtuvvwwxyzzzz|~~{wsqpqrtuvvuuuuuuuvwwurnkijmnjgfgimprrssttsppqstvwvsrssstttuvxyxtpqvz{|}~¦¬±¶¹¹¸·¶¶·¸¹»»¼¹µ®¥
¥µ¼½»¶®§£¬³¹»¹¸¸·³¯«¤
¥®¶¼¹±¯µº¾¿¾·¨¤³¸²®°±¬¨¦£}|~_______`bccccccdeffffffgghhhhhhgggjmpsuwxxvtrpnmoqstsqokgefghijjjknppnkihhijkmmnpqrtuvvustuvxz{{z|~~{wsqpqrtuvvttttttttutqnkheglmifdehjnpqsuwxxutuuvwxvspppoooooqtuurnpvz{|}~£©¯´¸¹¸·¶¶·¸¹»»¼¸³«¡§µ¼½¼¶£¥´º¼¹·¶´²¯§
~~
¨°¸½À¼µ³¹¾Âÿ¶¡¢²¹µ³·¼»¹·²¬¤
~~_______`bccccccdeffffffgghhhhhhhhikmorsuxxvtrpnnqrqqpnmjgefghijjjknppnkihhijkmmnoqtwxxvtrqsuwy{{{|~~{wsqpqrtuvutssssssronljhfegklhdcdgijlnquxzzyxxxxxxvqonmlkjjjmprrolnvz{|}~¢¨³·¹¸¸¶¶·¸¹»»¼¸²©©µ¼¾½·¬¡¦®µ»¼º·µ²±¯¯©¤¥ ~~¡§¬³º¿ÀÀ¼µµ»ÀÄÅÄÅĽ¯¶µ´¹¾¿½»µ¢_______`bccccccdeffffffgghhhhhhhijlmoqruwxvtrpnorsqomlljgefghijjjknppnkihhijkmmnnqvz{yvsppqtwy{|{|~~{wsqpqrtuvusrrrrrrojggggffhkkgdcdfgggjnswz|{{zzzyyvqnlkihffgimopnknuz{|}~
¥«±µ¸¹¹··¸¸¸º¹º·±¨¡¨°¶¹º±§ ¨¯¶ºº¹¶µ²²±±®¤¦£~}}¡¥ª¬®±³¶»ÀÁÁ¿»¶¶»ÀÂÃÃÆÊÆ·¨©²´´¸¼¾½»µ«
```````acdccccbcdeeffffgghhhhhhhjklnpqsuwxvurpnnrrpnlkkjhghhijkkkloppnkhiijjkmmmnpuxxwtqpprsvxyz{|~~zvrqqrstuvvsqqponnkgdeffggijifdccddddgjoty{|||{zzzwqnmlihffegknomklswwxy{}~¢§¬²·º»¹¸¸··¶¶µ³®¦¡¤§¦§¥¤¢ª±µ¶¶·¶µµ´´µ¯¤§§¥ ~|} ±¼º¸¹¼½¿ÀÁÂÁÀ¾¹¹»½¿ÀÁÃÉÇÀµ§
£¯¶¸¹»¿À½·®¢¡¥«ª cccccccddddcbaaabcddefghhiiiiiiijklnprtuwwwuspmnpqonmlkkjjjkkkkkkmoqpmihijjkkkklnopqrqppqqrsstuvy|~~|yurrqrsuvwuqomkigedeeeeffgghhfdcccbbabeiouxzzzzzzywqnmlkiigegknnnklppooqtwz ¤ª°µ¹ºº¹¸·¶µ´³±¬¥¡¤¤¥¦¤ £«±´´µµ¶¶¶¶¶¶²¦«¬«§¡~~£¸Á¿º»¾ÁÁÁÁÁÁÁ¿¼º»¼½¾¿ÁÅÆû®¤±¹½¼¼ÀÁ¾¸¯¤¤¬±¯¦dddddddeeedcba``abcdefghhiiiiiiijkloqsuvwwvtrommnponmlkkkllllllllnpqpmihikkkkkklmnnnnnnopqqqqqqsx{}~|ytrrrstuvwvpmkifdbbefffffffggfedcbbaaacglrvwwwwwwwupm
lkjihgegknonllmnlkmpuw¤©¯´¹ºº¸·¶µ´³²¯©¢¢§«¬¬ª¥¢©¯²´µµ¶¶¶¶¶¶°¢ ¬²²°¨£¦ºÂ¿º¼ÀÁÁÁÁÁÁÁÀ¼»¼½¾¿ÀÂÅÆľ²£ªµ½ÁÁÁÁÀ¼µ¬¢¦¯´³¬¢dddddddeeedcba``abcdefghhiiiiiiijkloqsuwwwtrpnmmnonmlkjjkkkkkkkkmoqrqnjhjkkkkkklmnnnnnnnnnnnnnnpvz}~}yvsrrstuvwuplkigdccefffffffggfedcbbbbabfkqstssssssqmjihgfedegknonlloomkmptv¢¨®³·¹¸·¶µ´³²±«¦¤«²´²¯©¡ ¦¬°´µ¶¶¶¶¶¶¶±§¡¡ ¤±·¶´±®«¥«¼Â¾»½ÁÂÁÁÁÁÁÁÀ½¼½¾¿ÀÁÃÄÆÅÁ¸«¤·¾ÂÄÄ¿¹±¨¦°··±¨¢dddddddeeedcba``abcdefghhiiiiiiijkloqsuwxvsomllmnnmlkjiiijjjjjjkmprsrokijkkkkkklmnnnnnnnllllllloty|}}zwurrstuvwunkjhgedeefffffffggfedcbbbbaadinpqppppppnjhgfedccdgknonlmopnllort¡§²¶··¶µ´³²±®¨¢©²¸¹·²ª¡¢¨®³¶¶¶¶¶¶¶¶²ª¦¤£¡ £´·µ²°¯¯¬¢°¾Ã¾»¿ÃÃÁÁÁÁÁÁÀ¾½¾¿ÁÂÃÃÄÆÇž³¨¥¬´»¿Âý¶£¤¯·¹´§dddddddeeedcba``abcdefghhiiiiiiijkloqsuwyvqlijlnmmlkjihhhiiiiiiknqtutplkjkkkkkklmnnnnnnnlllllllnsw{}}|yvsrstuvwumiihggfff
fffffffggfedcbbccaacgknooooooomjhgfedccdgknonlmqrollnps ¦¬±µ¶¶µ´³²±°¬¥£°¹½¼¹³©¥¬³¶·¶¶¶¶¶¶³«§¥£¡£¯³°«¬®®©~£´Áþ»ÀÅÃÁÁÁÁÁÁÀ¿¾¿ÀÂÃÄÄÃÅÈÈú°¤¢§³¸»¿À¼³© ¬¶¹µ®©dddddddeeedcba``abcdefghhiiiiiiijkloqsuxyvohfhlnmlkjihggghhhhhhjoruvuqmkkkkkkkklmnnnnnnnnnnnnnnorvy}~}zwsrstuvwtlhhhhhggffffffffggfedcbbdca`aeiloppppppoljihgfedegknonlnrtpmlmoq¥«°´¶µ´³²±°¯«£¨¶¿À½¹²§£«³··¶¶¶¶¶¶³«§¥¢ ª©¥¥§ª®®¤~¨¸Ãľ¼ÂÆÄÁÁÁÁÁÁÁ¿¿ÀÁÃÄÅÄÃÅÉËÇÀ·¬ ¤ª¯´º¾»±¥¨³·µ®©dddddddeeedcba``abcdefghhiiiiiiijkloqsuxzvmfdglnmkjihgfffggggggjosvwvrnlkkkkkkklmnnnnnnopqqqqqqqruy}~}{xtrstuvwtkgghhhihgfffffffggfedcbbdda``cgkprrrrrrqomlkjihgegknonlntuqmklno£©¯´¶³±²±¯¬«§ »Â½·®£¡©±µµ´µµµµ´±¬§£¨ª¤¢§®§®ºÂ¾½ÁÅÃÁÁÁÁÁÁÀ¿¿ÀÁÂÂÁÀÄÆÊÊÇ»³ ¤§ª±º¸«£¤°µµ±ccddeefgfedcba``aabcdefghiijjjkklmnprsuwyunifhmnmjjhgeddfffgghhjptvwvspnlllkkkklmnnnooop
qrssssrqrtx|~~|ztstvvwwsjfffghhhgfffffffgffedcbbcca_`behpssssssrqonmlllkhilnonmnrsqommmn¡¡ ¥¬²²±¯¯®«§£¦±¼Á¿¹°¥¤ª¬®¯°±²²²²¯ª¢¤ª© ¥©ª§´»¾¿¿¿ÁÂÁ¿¿¿¿¿¿¾½½ÀÁÀ¾¼¾ÅÉÈÇÄÀ½·¡ ¢«³¶¶¶abbdfhiifedcba`__``acdefhjjklmmoprrssttuutqnmmnmljigedccfghhjjknruuuuutsonmmlkjklmnoopqqpqsuusqopsx|~~}yttwxywuohddeeeeeffffffffeedccbbbbbaaaabgorrrrrrrpnlkkmppmlmnnnmmopqqqpnm¤£¡£ª±³±°°®ª¤£«´»¾¹²©¡£¦¨ª¯°±³²®¤§«¡¦©¨¦¡~
¶¼½¾¿ÀÁÁ¿¿¿¿¿¿¿¾¾¾Áÿ¼¾ÅÉÇÄÁ¿½º¡¡ª²¶¹¹_`bdfhjjgedcba`____`bcdehijklmnpstttttttssrqponmljigfdcdgijklmnpsuuuuuutqoonlkkklmnopqrqpptvvtpnpsx|~~}yuuxzzxuogddddddeefffffffdddcccbccddddddgnqqqqqqqpnljkmqronnnnnnmmnqssqnl¥¤¢ ¢©¯³´´´±«¤¡¨¯µ¸·°¨¡¢¦ª¯³¶¶±©¢¢©°¢¨«§¥¡}
ª¸½¾¿ÀÁÂÁÀ¿¿¿¿¿¿¿ÀÂÅÇÆÃÀ¿ÀÀ¾¼º¸¶±¢¤¢¢ª±¶¸¸__acfhjigedcba`____`bcdeghijlmmorssssssssrqponmlkjihgfe
giklmopprtuuuuuutrppomllllmnopqrrpquwwuqopsx|~~}yuuxzzxuogddddddeefffffffddddddeehiiiiiikoqqqqqqrqpmjjlpqonnnnnnmmnqssqnl¦¥£¡¡§²¶¸·³¥¦²³²®¤¤¬²··´§¤£¥ª°¬¢¨ª§¤ |¡±»¾¿ÀÁÂÃÂÀ¿¿¿¿¿¿ÀÃÅÇÈÇÿ¹°«ª©§¦¥ ¤¦¤£«±µ¶¶]^`bdghhgedcba`____`bcdefghijklnqrrrrrrrrqponmlljiiihhhimooqrsttuuuuuuutsrqpommlmmnopqrrqrvxxvrppsx|~~}yuuxzzxuogddddddeeffffffedddeffgikmmmmmmnpqqqqqqrsqnkjknoonnnnnnmmnqssqnl§¦¤¢ ¥ª¯¶¸¸µ°©¢©°³¯©¢¦¯µ·´¯ª§¥¥©ª ¥¨¥£{¤´¾¿ÀÁÂÃÄÃÁ¿¿¿¿¿¿ÁÄÇÇƽ·® ¤¦¤¤«±´´´\]_aceghfedcba`____`bcdeefghijkmpqqqqqqqpponmlkkiiijjjkmprstuvwwvuuuuuuussrqponmmmnopqrrrtwyywtqpsx|~~}yuuxzzxuogddddddeeffffffedcdfgijlnpppppppqqqqqqqstsokjjlnnnnnnnnmmnqssqnl¨§¦£¡¢§³¶·¶³®¨¢©±±ª
©°´²¯«¨¥£¦©¦¡¥£¢z¡³¾ÀÁÂÃÄÅÄÁ¿¿¿¿¿¿ÁÅÆÄÀ¹°¨¢¤¢¥¬°³³³[\^`bdfgfedcba`____`bc
ddeefghijlopppppppoonmlkjihiijklmpsuvwyz{zvuuuuuuuttsrqpoommnopqrssuxzzxurqsx|~~}yuuxzzxuogddddddeeffffffeccdgiklnopppppppqqqqqqqsutpliiklnnnnnnnmmnqssqnl©¨§¤¢ ¡¥ª¯³¶·¶³¯¨¨°¯¤£«¯¯«§£ ¢¤¡¡¡¡~y¯¾ÁÂÃÄÅÆÅÁ¿¿¿¿¿¿ÁÄÅÀ¹®£¡ ¦¬°²²±Z[]_adeffedcba`____`bcddddefghiknoooooooonmlkjiihhikmnorvxyz{|}|wuuuuuuuuutsrqponmnopqrstvy{{yvsqsx|~~}yuuxzzxuogddddddeeffffffeccegjmooonnnnnnopqqqqqqswvqliijlmnnnnnnmmnqssqnl©¨§¥£¡ £§±³¶¶¶´¯¦ ¤«©¢®ª¦¡¡ {¯½ÀÂÃÆÇÈÆÃÁÀÀÀÀÀÂÃÀ¹®£ ¥ª®±±°[\]_acdeedccba``___`abccdfggghijlmmnnnoooonmllkjijklnoprwyyz{||{wuuuuuuuvuutsrrqonoopqrruwyzzywtsuy}~~|yuvxzzxtohedccddeefffeeeddeghkmoooooooooppqqqqqqsutpmjjjlmmmnnnnnnoqrrqom¨¨§¦¤£¢ ¡¢¦«¯±³µ¶¶¶¯ª£ £ «¯ª¥ ¢
¡®´·»ÀÄÇÈÈÅÄÃÁÀÀÁÁ½¶«
¢§«¯±\\]_`accbbbaaaa`____```cgiiiihhhijklnopqooooonnomnnoopprvwxxyyywusssssstuvuuuutspooppppsuwxyyxwwuw{~|zwuvy{yvspkifcbbdffffeeddfhijkllmopqqqqqqqppppppppqpommlmlkkllmnoooopqqpoo¨¨§¦¥¤£¡¡¡¥ª®¯±²´µ¶µ°¨«¯®«¦¢¢
¥§©°¹ÀÅÇÈÆÅÄÂÀÀ¿½µ¬¡ ¤¨¬¯±]]^_`abbaaaaaaaa_______bhkkjjiiiijklnoqqppppppppppppppprtvvvvvvutsssssstuvvvvvvuqppppppruwwwwwwwwy|~~|ywuwy{yvrqqojecbdefffeeddfjllllllnprrrrrrrppppppppnnnnnnnmkjklnopppppppppp¨¨§¦¥¤£¡¡¡¤ª®¯°±²´µ³¬¥§®¬¨¡¡¢¤¢¡®¹ÁÅÆÆÄÃÁ¿¼ºµª¡£¨¬°±]]^_`abbaaaaaaaa_______bhjkkkkkkkllmoppqpppppppppppppppqtuuuuuuussssssstuvvvvvvuqpppppprtvvvvvvvvx{}}{xvuwy{yvrswvpieccdeffffffhjllllllmpqqqqqqqppppppppnnnnnnnmlklmopqqpppppppp¨¨§¦¥¤£¡¡¡¤©««¬¬¬¯²²®ª¦¢ £«®®ª¢¡£¥¥¢§µ¿ÄÅÄÃÃÁ½¸³¬
¡§¬°²]]^_`abbaaaaaaaa_______bgjkklmnnnnoooppppppppppppppppppqqrrrrrrrssssssstuvvvvvvuqppppppqtuuuuuuuuwz||zwuuwy{yvruz{tlgcbcdefgghijkllllllmopppppppppppppppnnnnnnnmmmmnpqrrpppppppp¨¨§¦¥¤£¡¡¡¤§©©©¨¨¨©¬¬ª§¤¡ ¨°¬¤¡£¥¥¢{§·ÀÃÃÃÂÃÀ»³«¢ ¢¢ ¦¬±³]]^_`abbaaaaaaaa_______agjklnopqqqqqpppopppppppppppppppppppppppqrsssssstuvvvvvvuqppppppqsttttttttvy{{yvtuwy{yvruz{tlgcbbdefgijlllllllllmnoooooooppppppppnnnnnnnnmnopqrsrqppppppp¨¨§¦¥¤£¡¡¡£§¨§¦¥¤£¢¢¤¥¦¤¡¦±¯¦¡¢£¡°½ÄÄÂÁÁÂÀ¹¯¤¤§¥¢¦¬±´]]^_`abbaaaaaaaa_______bfikmoqstttsrqpooppppppppppppppppnnnnnnnorsssssstuvvvvvvuqppppppqrssssssrsuxzzxustwy{yvrswvpiecccdefhjmnnmllllllmmnnnnnnoopppppppnnnnnnnnnopqrstsqppppppp¨¨§¦¥¤£¡¡¡£¦¦¥¤¢¡ ¡¡¤²±¨¡
§°«»ÆÈÆÂÀÁ¿·«¦ª©¤¥¬±´]]^_`abbaaaaaaaa_______afiknqsuvvvusrpoooppppppppppppppomllllllnqsssssstuvvvvvvuqppppppqqrrrrrrrrtwyywtstwy{yvrqqojecbddddfilnppmlllllllmmmmmmmnopppppppnnnnnnnnopqrstutqppppppp¨¨§¦¥¤£¡ ¢¤¤¢ £¤£¡£¬²²©¡ ¬¸¡±ÁÊËÇÂÀÁÂÀ·© ©«¥£«²·]]^_`abbbbbbbbbb_______agjloqtvvwvttrqppoppqqqqrqpppppppljkkkllmqssssssttuuuvvvurppoopprqrrrrrrrsuxyyxutvyz{yupnmkgcabdeddfhkmoomlkkkkjjlllllllmnooooooomnnnnooopqqrstttrqqqpppp¨¨§¦¥¤£¡ ¤£ £££ ª±±ª¡¡£ ¹°¿ÉËÈÃÀÁÿ¶¨¡«°¤ªµ»[[\]^``abbbbbbbbaaaaaaadjmnorstttssrrqqqppqqrstsqqqqqqqnjiijkllorssssssrrqrstuvvrqnmmnqrsssssssuuwxyyxwyz}}|xrmlllgcaacdeefhikllljjihgghijjjjjjjlllllllllllmoopqqqrrrrssssrqqpon¨¨§¦¥¤£¡¤ª¢££¡
©°±«¢¢¤
·½ÇÉÇÃÁÁ¾´§¡«¯¬£¨µ¼[[\]^``accccccccbbbbbbbeknopqrssqqqqqqqpppprstutrqqqqqqojhijkmmoqrrrrrrrppqrtuvvsqnllnqstttttttuxyyyyyyz}~|xqkjmmhdbbcdeffhijkkkjihgfefghhhhhhiijjjjjjjkllmopqqrrrrrrrsstsrqpon¨¨§¦¥¤£¡ ¡£¥¥§¯µ¯¢ ¥¦¤¡¨°±¬£ ¢
®¸¼ÆÈÅÂÀÀ¿»±¥©©¢¦²¹[[\]^``bcdddddddcccccccfjmnopqrrqppppppooopqrstsrqqqqqqojhijkmmopqqqqqqqppqrtuvvsqnllnqsuuuuuuuvxyyyyyyz}~|xqkjnnieccdefggijkllkjihgfefghhhhhhhiiiiiiiikllmopqrrsssssssttsrqpon¨¨§¦¥¤£¡ ¡ £¦©¬±¸»³¤¤ª©¥ §°²¥
¯º¼ÄÅÂÀ¿¿¼·¢¦ª¦£®µ[[\]^``bdeeeeeeedddddddfjlmnopqqonnnnnnnmnopqrssqqqqqqqojhijkmmnppppppppppqrtuvvsqnllnqtuvvvvvvwxyyyyyyz}~|xqkknojfddefghijklmmkjihgfeffggggggghhhhhhhijllmopqrstttttttttsrqpon¨¨§¦¥¤£¡ ¡¢¢¡¢¥¨«®°²·
¼¾´¦¡ª¯¦ ¦¯²®§ ±¼»Ãÿ¾¾½¹²©£¦£ª±[[\]^``bfgggggggeeeeeeegiklmnopolkkkkkkklmmopqrrqqqqqqqojhijkmmnooooooooppqrtuvvsqnllnqtvwwwwwwxxyyyyyyz}~|xqkkoplgeefhhijklmnmljihgfeeeeeeeeeffgggggghjllmopqrtuuuuuuuttsrqpon¨¨§¦¥¤£¡ ¡¢£¥§©«¯±²³·»¼³¥ ¦°´°¨¥¯²¯¨
¡³¾ºÁÁ½»½¼¶®¥ ¡£¦[[\]^``cfhhhhhhhfffffffghjklmnonjiiiiiijjklmopqqqqqqqqqojhijkmmnnnnnnnnoopqrtuvvsqnllnqtwxxxxxxxyyyyyyyz}~|xqklpqmhffhijjklmnonljihgfeedddddddeeffffffgjllmopqruvvvvvvvttsrqpon¨¨§¦¥¤£¡ ¡¢£¤§°±±±±²²³¸¸°¤¡ªµ¸³©¤¯³°©
¢´¿ºÀÀ»º¼»´«¡ ¡¡¡¡¡¡¡¡¡¡¡¤ª[[\]^``cgiiiiiiiggggggghhijklmnmjhhhhhhhjklmnoppqqqqqqqojhijkmmnmmmmmmmnopqrtuvvsqnllnqtxyyyyyyyyyyyyyyz}~|xqklqrniggijkklmnopoljihgfeeddddddddeeeeeeefjllmopqsuwwwwwwvutsrqpon
§§¦¥¤¤£¡ ¡¡¢£££§®±°°°°±°²³±©¡¡«µº´¨©²³¯«¦§µ½¬¹¿¾º¸½½¶£ ¢¡¡¡¡¡¡¡ £¢¨\\]^_aacghhhggggfffggghhjkkmmnomjiiiiiiijklmmnooqrrrrqomihhijkkllllllmmmnprsvvwvsqnllnqtxzzzzzzzzzzzzzz{}~{xrlmstniggijjjklnoookihggfeeddddddddeffffffgkmmnoppruwwwwwwvutssrqpp¤¤¤¤¤£££¢¢¡ ¡¤¦¥£££¤¥©«¬®¯°±´´±¨ ¢¬´¶¯¥¥²·³®© ¯µ³«·¾¿»¼¿À»³ª ¡¡¡¡¡¡ ¢§¤¡ ¦]^_`abcdfgfeedcbddeeghhjlnnnooonljjjjjjllmmmnnnprsuusolihghhhiihhhijkkllmnrvxywvtqnllnquyzzzzzzzzzzzzzz{}}{yuqortuoieegghghikllkhfffeeeedddddddffggggggjnppoooopstttttttuuutttts¤¤¤¤¤¤¤¤¤¤£¢¢¡ ¢¦¨§¦¦¦¦§¨ª¬®°²´·¸³¨ ¥®³±ª ©·¹²¬¬
¦´µª·¿ÂÀÀ¾·®¢ ¢¨«¨¡£__`abcdeggfedbbbbcdeghijmnnnnnnmkjjjjjjknooooooprtuusojhhiiiiiiigghijklllnswzzxvtqnllnqtxyyyyyyyyyyyyyyzzzxvspoqttnhddefefghijkjfeeeeeeeeeeeeee
fghhhhhhjopppooopsttttttuuvvvvvvv¥¥¥¥¥¥¥¥¥¥¥¥¥¦¦¦§¨©ª«¬«¬¯±³µ·¹¼»¶¬¥¤©±³¬£©·¹±ª««¢¦²²©¨µ¿ÅÇÇÅÿ¹°¥¥ª©¢``abcdeghhhfedccccdeghijjkkkkkkjihhhhhhjnppppppprsuurnihjllllllkihijklmmlnswzzxvtqnllnqsuuuuuuuuuuuuuuuvvvuspnmorrmheccddefghijjgffffffffffffffgghhhhhhjmoppppprtvvvvvvwwxxxxxxx¥¥¥¥¥¥¥¤¤¤¥§¨ª««©ª®°²²°¯°±³µ·º»½»¶®¨§«±°¥ª·¸°¨©ª¥¤®¢¤°»ÄËÌÇÃÁ»²¨
aabcdefhjjjigffeccdeghiiiiiiiiihgffffffinqqqqqqqqrttqmhhloooooonjijklnnnlnswzzxvtqnllnqrrqqqqqqqqqqqqqqrrrqpnmlmqqnjfdbbcdefghiigggggggggggggggghhhhhhhjlnoopqqswxxxxxxyyzzzzzzz£££££££¢¡¡£¦©¬®®®°´¸¸¶²°®¯±³µ·¹¹·²¬§¦©ª ª··®¦¦¨¤ §¤¥±½ÇÊÇĽµ¬£
bbcdfghilmlkjihgdcdeghiiiiiiiiiihhhhhhhkorrrrrrqqqrrplggloooooonkkklnopnmnswzzxvtqnllnqrqpppppppppppppppqqppon
noqsqnkgdbbcdefghhhhhhhhhhhhhhhhhhhhhhhhhiklnoqrsvy{{{{{{{||||||||£¨¬¯±´¸¼¿¾¸²¬¨¨ª¬®±²²©¥¡ ¢¥¢¡¢«··¤£¥ ¢°¼ÃÆÅÿ¸¯§¡{z{}
ccdeghiknonmlkjhecdeghijjkkkkkkkkkkkkkkmqssssssrppqqokffilllllllkllnopqomnswzzxvtqnllnqrrqqqqqqqqqqqqqqqrrqrqqqruvvuqlgdabcdefghhiiiiiiiiiiiiiiihhhhhhhhjkloqsuw{}}}}}}}~~~~~~~~¥ª®²º¿ÄÅÁ¹°§¡ ¢¤§©ª©¤ £¤«·¶¬¢¡¡¡¯ºÄÆÄÀº±©£~~ddefhijloqponmliecdeghijmnnnnnnnooooooopsttttttrpoqqnjedgiiiiiijkmmopqrpmnswzzxvtqnllnqsttttttttttttttttstttuuvwxz|{xrkfbabcdefgijjjjjjjjjjjjjjjhhhhhhhhijlnqtvy}¤¬±¶ÀÆÊÉŤ ¢¥¥ £¥ ¬¶¶¤£¡
¤¯ÀÅÃÀ¹¯¥
ddfhiklnpssrpnkha_abdfgimooppppqoooopppqqrrrsstrppppmifefhhhhhhikmmnopqonotwz
ywuromllnpruuuuuuuuuuuuuuuuuuvvwwwxyz}}{upkdbbcegjljjjklllmkkkkllllkjjiihhggiloruwz{}~~}}©²ºÃÈÎÑÏÇ»®§¡ ££ ¦¯³³¯ª¦
¬½ÃÁ¼²¦¡
dfhjmoqrrstspke^YXY\_acfkmnnopqokjklmnonmmnpqsstqppnliggfggggggiklmmmmmmnptxyxvrnlllmnpruvvvvvvvuuuuuuuuvvvvvwwvvxz|{wrngdccflqpkijklnonlklmmnoonmlkihgfeglrvxxwxz}}zy}£¯ºÂÈÍÐÓÒÌÁµ®ª¦¡¢£¡ ª¯±±°¬§£¯½Á¾· ¡¢
hikmpsuurrsqmg`ZTTVX[^`chjklmnonkijklmnnmmnpqsttsqpnkihghhhhhhhikllllllmoruxywtpljklnopqtuuuuuuuuuuuuuuuuuuuuuuuuwyzxuqmhfeeioutmhiklnonlklmnopponmkjhgfehntxyywwy}}yx|~~~~~~~ «·ÂÊÍÏÑÔÕÑÊ»³®©£¡¡¡ ©®¯¯¨¤¡¸¿Àº²¨
mnprtvxvronlga[VTTVXZ\^adghijkllkllnopqqpqqr
tuuusqpnkihghhhhhhhikllllllmpsvxxvsplklmopqrtuuuuuuuuuuuuuuuuuuuuuuvxz{zwrligffhkputlhijklmmkjklmnoonmlkjiiggjpuxyyxz|~~|{}~~~~~~~¦³ÀÊÑÒÑÒÕ×ÖÒÎǾ¸³¬¦ ¡ ¡©¬¬©¤~©·¿Â¾µ« ¡
rstuwxzwqmjf`ZVTSUVWYZ[]abcdfghikmnopqrrsstttuutsqpnkihghhhhhhhikllllllnquwyxuqnmmmnpqrsstttttttuuuuuuuutttttttvy||zuoheefhknrvsmiijjjkjiijklmnnllkkkjjijlrvyyxx{|}~~}|}}~~~~~~~«ºÇÑÖÖÓÓÖØØ×ÕÐȾ¸±©£ £©ª«©¥ ¯»Ãý°£¡¢ uvvwxyywrmhb[VSRTUVVWXYZ\^_`abceillmopqrsttssrrrrqpnkihghhhhhhhikllllllnsvxyxtpmmnopqrssrrrrrrrstuuuuuutsrrrrrrtx{zxtngddgjnrtvtmiiihhhhghijklmlkjjkkklllotxzzxxz{zyyz{|~~~~~~~~¾ÌÕÙØÖÕÖ××Ø×ÔÏËÉž¶¯¨¡ ¥¨¨¨¦¢
¥°¹Àû«¢£¢ vvvvvvwvtph
`YTRRTVVVVVVWXZZ[]^_afhijklmoqrqponmnqqpnkihghhhhhhhikllllllotxyywsnlmopqrstsrqqqqqqrtuuuuuutrqqqqqqruwxwsniedglquvvsmjihgfeefggijklkiiijklmnorvy{zwwxwussuwz}~~~~~~~¿ÎÖÚÙØÖÕÕÕÕÖÕÒÒÒÏÊ»²§¢¡ ¢§¨§§¤§¯µ¼Áº¨£¤¤¢¡ ¡ uuuttssuvsj`YTSTUVVUUTTUUVWXY[[^bdefghilnonmkihkoqpnkihghhhhhhhikllllllouyzzwrmlmpqrstutrqqqqqqrtuuuuuutrqqqqqqqprtutplgegntwxwsmjihfeccefghijkjhhijlmnortx{{zwvusommosx|~~~~~~~¬¾ÍÖÙÙ×ÖÕÓÓÓÔÔÔÔÕÔÑÌƾ°«¨¥¡ £§§¦£¦²º¾¶¤ £¥¥¡¡¢¡ ssrrrrqtusj`YUTUUVUUUTTTUUVVXYY[^abdfhikopnlihhkqsrolihfgghhijjkkklllmmouxxwurnnopqrsstsrppppppqtuuuuuutqpppppppnoqsrpnkfiovxxvrljigfeddefghijjjgfhjlnpqqsw{|{xwtrommorv|~~~~~~~«½ËÓÖ×ÕÔÓÓÓÓÓÓÔÕÕÕÔÒÐÌÀº´¥¢¤¤¢¡©°µ¶£¯©¢¡¥¥¢¢¡ ¡
pppqqqrrrnf_YVUUVVVVUUUUUUUVVVWXZ]_bfilqrrolkklquwtqmjgffghjlmnnlllmoopruusqppqrpqqqqrrrpppppppqrsssssssqqqqqqqpnnooponljlrvxvsnkhhhggfgghhhiiigeegimoqomnuz}}{xusrqqrsw{}}}}}}}¾ËÒÕÕÔÓÓÓÓÓÓÓÔÔÔÔÔÔÔÒËÅ¿¶¬£¡¡ ¢£¡£ª¯®¦¢®µ®¢ ¤¤¡¡¡ ¢¢
qqqrrrssokd]XVUUVVVVVVVVVVVVVVVWY[^bfilptsollmpsxyvrnkhffgikmpqqoooprstutspnnpstrqqqqqqqpppppppqrsssssssqqqqqqqqooooooonnptvvsokihhhhhhiijjjjjjhfegjmorolmsy}}|yvuuuuuuw{}}}}}}}¤²ÁÌÓÕÔÓÓÓÓÓÓÓÓÔÔÔÔÔÔÔÔÑÎÉÁ¹²¦¡¡¤¦¦£ ¡¡¥¥¡¤®·¸®¡¡£¢£¢
uuuttttsnic\XVVVVVVVVVVVVVVVVVVWXZ\`cfilooljkmptxxvspljihikmoqststtuwxyxvspnnpstrqqqqqqqpppppppqrsssssssqqqqqqqqpppppppprsttrnjihiiiiiijjkkkkkkjhgiknpqplmsx{}}{wvvvvvvx{}}}}}}}£«¸ÅÏÓÓÒÓÓÓÓÓÓÓÓÔÔÔÔÔÔÔÕ×ÖÒÌÆÁ½·°®±±¥
¡§°ºÀ»®¡¢¤¥£
zyyxwwvsmga[WVVWVVVVVVVVVVVVVVVVWXZ]_bdgjjhgimquxxvtqnmljkmoqsuvxxyz{|}{wspnnpstrqqqqqqqpppppppqrsssssssqqqqqqqqqqqqqqqrttspmiffhjjjjjjkkllllllljjkmnpqpmnrvy|}|ywwwwwwy{}}}}}}}ª´¿ÊÑÓÒÑÒÓÓÓÓÓÓÓÔÔÔÔÔÔÔÖÙÙ×ÓÐÍÊž¼¾¼´¨|£¦¬³ºÁļ¢¦¨¨¦¤
}|{yxtjd_ZVVWWVVVVVVVVVVVVVVVVVVXZ\]_adeddhmrvxxvusqoommoqtvxyyz{|}}xspnnpstrqqqqqqqpppppppqrsssssssqqqqqqqqrrrrrrrstsplifefikkkkkkllmmmmmmmmmnnopppooqsw{~~zxxxxxxy|}}}}}}} °¼ÅÎÓÓÑÐÑÓÓÓÓÓÓÓÔÔÔÔÔÔÔÕ×Ø×ÖÔÓÒÏÊÉÊÆ»ª~¥«±·½ÀÂü¢¨«¬«©¤
}{ztia\XVVWWWVVVVVVVVVVVVVVVTTUWXYZ\^_`aflswxwvutsrqppqtvxz{zz{|}}xspnnpstrqqqqqqqpppppppqrsssssssqqqqqqqrrsssssssqokgeefhlmmmmmmmnnnnnnnooppppppppppquz|zzzzzz{|}}}}}}}
¸ÂÊÒÕÔÐÏÑÓÓÓÓÓÓÓÔÔÔÔÔÔÔÔÔÔÔÔÔÕÕÔÓÔÔÎÀ¬
£¦£
¡®¶¼ÁÿÀ»£©¯¯§
}{ug_[WUVWXWVVVVVVVVVVVVVVUTSTUUVVX[\\_elswxwwvuutsrqsuxz|{yyz{|}~|wspnnpstrqqqqqqqpppppppqrsssssssqqqqqqqrsttttttsnjfcceilnnnnnnnnooooooopqrqqqppqqqopsy~{{{{{{||}}}}}}}
½ÅÌÑÕÔÑÐÑÒÓÓÔÕÖÖÕÕÔÔÓÔÔÓÑÑÑÒÓÓÔÕÕ×ØÒį¢§ª§¢ªµ½ÁÄľ¾º¬¥¬¯±²±¨¡
~zse]YVUVVWWVVVUUUUUVVWVVUSTTTTUUUVXYZ]cksvxxxwwvvuttuvxxyxyyz{|}}|vspoopssrqqqqqqqpppppppqrsssssssqqqqqqrrssrrqponjgdbceikoooppooopqponnopstrqpppqrqppsx}~|{{{{{{|}}}}}}}¥ÁÇËÎÑÒÓÓÑÑÑÒÔ×ÙÚÖÓÒÐÐÐÑÒÑÑÑÑÑÒÒÒÔ×ÙÕȵ¡
£ªª£¥µº½ÀÂÃÃÁ¿À¸©§±²°²±ª¥¢
}vk`YXVUTTUUVUUUTTSUVXYXURRTUUUUUUVVVX[`hotxxxxxxxyyyxvtsqtz|||}}~zuqqppqqrqqqqqqqqqqqqqqqrrssssssrpopqqrrsqpoljhgefdcccefhmorssroqttpmmmnswxtponoppppqsuxz|||{{zz{}~~~~~~~«ÂÈÊÌÏÒÔÔÑÐÑÓÕ×ÙÙÔÐÍËËÌÎÏÑÑÑÑÑÑÑÑÒÕ×Õʹ§
¤ª¬¥¡¨¯¶¼¿ÁÁÁÁÁÁÁÁ¸¨¨³±®°²¯¬¬©¥
|si]XWVUTSTUVUUUTTTVXZ[ZWSRTVVVVVVVVVWY^elrwyyyyyyzzzxurpnqz~~~~~~{tqqqqqqqqqqqqqqqqqqqqqqrrssssssrpoppqqrqpnljgdcbcddddddflpsuuspqvvrnmmotyytpmmopopprstuw{}}||{{|}~~~~~~~¢±ÂÉËÍÏÑÓÓÑÐÒÓÔÕÕÓÌÈÄÂÂÅÈÌÐÑÑÑÑÑÑÑÒÕ×Õ̽®¢¦«®¨¢
¡§«®³¸¼ÀÁÁÁÁÁÁÁÁÁ¸§¨²°¬®±±±²²°«¦
{qg]XWVUTSTTUVUVVVWY[^_^ZVUUVVVVVVVVVVX]cjovxxxxxxxyxvtrpnqy}}}}}}zspppppppppppppppqqqqqqqrrssssssrqpppppponlkigdcccddddddflpsuusprwxuqpqtwzxsommnonopqrstv{}}}}}}}~~~~~~~~§µÅËÌÍÏÐÑÑÐÐÒÔÓÑÏËý¹¶·»ÁÈÎÑÑÑÑÑÑÑÒÔ×ÕÎöª
¡©¯¯¬§¥¥£
¨²¸º»½¿ÁÃÃÁÁÁÁÁÁÁÀ·¦©²¯«¬®®®°²±¯«§¢
yoe\XWVUTSTTUVVWXXZ]`bcb_[XVVVVVVVVVUUVZ`fltwwwwwwwvutsqporx||||||yrooooooooooooooppqqqqqqrrsssssssqpponnmlkjigfdccdddddddflpsuusprwyvssuxzywrnkkmnmnopqrsuxz{{|}~~~~~~~~~~
¬ºÈÌÍÎÎÏÐÏÏÐÓÔÒÎ
Èù²¬©ª±¹ÂÍÑÑÑÑÑÑÑÒÔÖÕÑÉÀ¶
¦¬®°°¯¬«¨£¥´½ÁÂÂÃÃÄÄÃÂÁÁÁÁÁÁÀ¶¥¬µ±¬®©¨«®¬©¨©©¥
vlc[XWVUTSSTUVWYZ[^adghgc_\WVVVVVVVUTSTW\birvvvvvvutrrqpporx{{{{{{xqnnnnnnnnnnnnnnopqqqqqqrrsssssssqqpnmkjihgffeddcdddddddflpsuusprvxussvy{yvqmjjlmlmmopqrrtuvwy{|}}~~~~~~~
¡²¿ËÎÎÎÎÎÎÎÎÑÔÕÑʺ°¨¡§±½ÌÑÑÑÑÑÑÑÒÔÕÖÓÎÈâ«®°±²³³³²²°¨¡©³¼ÁÂÂÂÃÃÃÄÃÂÁÁÁÁÁÁÀµ¤²¹µ°°°«ª¯®¬¨ª±³±«£
tiaZXWVUTSSSTVXZ\^aeiklkhd_XVVVVVVVUTRRUY^fpuuuuuutqpppppprwyyyyyyvollllllllllllllmpqqqqqqrrsssssssrqpnkihgeedddddddddddddflpsuuspqstqpquxzyupkiiklkklmopqpnnprtvxz}~~~~~~~
¤¶ÃÍÏÏÎÎÍÍÍÍÑÔÕÑȾ´© ¬ºËÑÑÑÑÑÑÑÒÓÕÖÕÒÏͧ®°±²³µ·····¶²«¥¥³½ÁÀ¾½½¾¿ÀÁÂÂÂÁÁÁÁÁÁÀ´£¥·¿º´´¶¶¶¸¹·´¯±·»º¶¯¦
~sg_ZXWVUTSSSTVY[^`chlnpnkgbYVVVVVVVUSQQSW[cottttttsonnoopprwyyyyyyvollllllllllllllmpqqqqqqrrssssssssrpmjhfeccccddeedddddddflpsuuspoppnmorvywtokhhjkjklmnopmigilo
qsv|~~~~~~~
¦¸ÅÎÐÏÎÎÍÌÌÍÑÕÕÐÆ»±¥©¶ÌÑÑÑÑÑÑÑÒÓÕÖÖÔÒÑ¡ª°±±²´·¹º¸¹»»¸²«¢®ÀÉÈÁ»¸¹º¼¾ÀÁÂÁÁÁÁÁÁÁÀ´¢¨»Â½¶¶»¿ÂÄÃÁ¼··»¿¿¼¶¤
}rf_YXWVUTSSSTVY\_adjnpqpmibZVVVVVVVTSQPRVZbnssssssrnmmnopprvxxxxxxunkkkkkkkkkkkkkkmoqqqqqqrrssssssssrpmjgecabbccdeedddddddflpsuuspnnmkklpuxvsojhhikjjklmnolfcehknpt{~~~~~~~
<p>1.1 theora/doc/txt2html.py
Index: txt2html.py
===================================================================
#reformat python script as HTML
comface = "Times New Roman"
codeface = "Courier New"
import fileinput
import sys
pagewidth = 118
if len(sys.argv) < 3:
print "usage: python tab.py inputfile outputfile"
print
print
x = 0/0
ofil = open(sys.argv[2], "w")
#ofil = open("2.txt", "w")
ofil.write("<html><body>")
tate = "code"
#note that formatting characters must be in sequence: #, _, /
for o in fileinput.input(sys.argv[1]):
oldstate = state
if (o[0] == '#') and (o[1] != '*'): #if this line is comment-only
state = "comment"
top = ""
cap = ""
if (o[1] == '#') and (o[2] == '#') and (o[3] == '#'): # '####' means big header
top += "<h2>"
cap += "</h2>"
o = o[3:]
elif (o[1] == '#') and (o[2] == '#'): # '###' means header
top += "<h3>"
cap += "</h3>"
o = o[2:]
if o[1] == '#': # '##' means emphasis on this line
top += "<b>"
cap += "</b>"
o = o[1:]
if o[1] == '_': # '_' means underline
top += "<u>"
cap += "</u>"
o = o[1:]
if o[1] == '/': # '/" means italics
top += "<i>"
cap += "</i>"
o = o[1:]
if state != oldstate:
ofil.write('</pre><font face="' + comface + '">')
ofil.write(top + o[1:] + cap + "<br>")
else:
state = "code"
if (o[0] == '#') and (o[1] == '*'): # '#*' is preformatted comment
o = o[2:] # remove them
if state != oldstate:
ofil.write('<font face="' + codeface + '"><pre>')
ofil.write(o)
ofil.write("</body></html>")
ofil.close()
<p><p>1.1 theora/doc/txt2py.py
Index: txt2py.py
===================================================================
#reformat long comments and replace tabs
#default tab spacing = 6 (for wordpad)
import fileinput
import sys
pagewidth = 118
if len(sys.argv) < 3:
print "usage: python tab.py inputfile outputfile"
print
print
x = 0/0
ofil = open(sys.argv[2], "w")
for o in fileinput.input(sys.argv[1]):
if o[0] == '#':
if o[1] == '#':
o = '#' + o[2:]
if o[1] == '#':
o = '#' + o[2:]
if o[1] == '*': #remove formatting hints
o = '#' + o[2:]
if o[1] == '_': #remove formatting hints
o = '#' + o[2:]
if o[1] == '/':
o = '#' + o[2:]
if (o[0] == '#') & (len(o) > pagewidth):
w = o.split() #create list of words in string
x = 0
while x < len(w):
if x > 0:
p = '#'
else:
p = ''
while (len(p) + len(w[x])) < pagewidth:
p += w[x]
p += ' '
x += 1
if x >= len(w):
break
p = p.rstrip() #remove last space
ofil.write(p)
ofil.write('\n') #linefeed
else:
ofil.write(o)
ofil.close()
<p><p>--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list