Hi
Had a look at the theora file format and have started to write a loader for blitz. At the mo... I've nearly completed the header loaders. Still a bit of work to do.
As Theora is open source... heres my code for blitz (its very messy at the mo). If any one wants to add to it.
All docs can be found at www.theora.org temp3.ogg was created using the ffmpeg2theora util found on the above site from a standard AVI.
SuperStrict
Type theora_typ
Field bank:TBank
Field stream:TStream
Field pos:Int
Field VMAJ:Int
Field VMIN:Int
Field VREV:Int
Field FMBW:Int,FMBH:Int
Field NSBS:Int,NBS:Int,NBMS:Int,NMBS:Int
Field PICW:Int,PICH:Int
Field PICX:Int,PICY:Int
Field FRN:Int,FRD:Int
Field PARN:Int,PARD:Int
Field CS:Int
Field PF:Int
Field NOMBR:Int
Field QUAL:Int
Field KFGSHIFT:Int
Field vendor:String
Field comments:String[]
Field LFLIMS:Int[64]
Field ACSCALE:Int[64]
Field DCSCALE:Int[64]
Field BMS:Int[385,64]
Field NQRS:Int[2,3]
Field QRSIZES:Int[2,3,64]
Field QRBMIS:Int[2,3,64]
End Type
Global t:theora_typ
Global bits_val:Int
Global bits_b:Int
LoadTheora("temp3.ogg")
Function LoadTheora:Int(file:String)
t = New theora_typ
T.stream = OpenStream(file)
SeekStream(t.stream,28)
If Not Header_ID() Then End
SeekStream(t.stream,109)
If Not Header_Comment() Then End
If Not Header_Setup() Then End
CloseStream t.stream
End Function
Function Header_Setup:Int()
Local nbits:Int
Local i:Int
Local j:Int
Local NEWQR:Int
Local qti:Int, qtj:Int
Local pli:Int, plj:Int
Local RPQR:Int
If Header_Common("82") = False Return False
Print "header setup found"
nbits = readbits(3,True)
Print nbits
i = 0
While i < 64
t.LFLIMS[i] = readbits(nbits)
i:+1
Wend
nbits = readbits(4) + 1
i = 0
While i < 64
t.ACSCALE[i] = readbits(nbits)
' Print i + " " + t.ACSCALE[i]
i:+1
Wend
nbits = readbits(4) + 1
i = 0
While i < 64
t.DCSCALE[i] = readbits(nbits)
' Print i + " " + t.DCSCALE[i]
i:+1
Wend
t.NBMS = readbits(9) + 1
Print t.NBMS
i = 0
While i < t.NBMS
j = 0
While j < 64
t.BMS[i,j] = readbits(8)
j:+1
Wend
i:+1
Wend
qti = 0
While qti<2
pli = 0
While pli < 3
If qti>0 Or pli>0
NEWQR = readbits(1)
Else
NEWQR = 1
EndIf
Select NEWQR
Case 0
' copy
If qti > 0
RPQR = 1
Else
RPQR = 0
EndIf
If RPQR = 1
qtj = qti - 1
plj = pli
Else
qtj = (3 * qti + pli - 1)/3
plj = (pli + 2) Mod 3
EndIf
t.NQRS[qti,pli] = t.NQRS[qtj,plj]
i = 0
While i<63
t.QRSIZES[qti,pli,i] = t.QRSIZES[qtj,plj,i]
t.QRBMIS[qti,pli,i] = t.QRBMIS[qtj,plj,i]
i:+1
Wend
Case 1
' new set
EndSelect
pli:+1
Wend
qti:+1
Wend
Print "header setup complete"
Return True
End Function
Function ReadBits:Int(nbits:Int,reset:Int=False)
Local tmp:Int
Local val:Int
' mask
tmp = (Ceil(2^nbits)-1)
' if reset
If reset = True
bits_b = 0
bits_val = (ReadByte(t.stream) Shl 8) + ReadByte(t.stream)
EndIf
' Print Bin(bits_val)
' Print Bin(tmp)
val = (bits_val Shr (16-(nbits+bits_b))) & tmp
bits_b:+nbits
If bits_b > 7
bits_b:-8
bits_val = ((bits_val Shl 8) & %1111111100000000) + ReadByte(t.stream)
EndIf
Return val
End Function
Function Header_Comment:Int()
Local ln:Int
Local i:Int,j:Int
Local ncomments:Int
If Header_Common("81") = False Return False
Print "header comment found"
ln = ReadByte(t.stream)
ln:+ ReadByte(t.stream) Shl 8
ln:+ ReadByte(t.stream) Shl 16
ln:+ ReadByte(t.stream) Shl 24
' vendor
t.vendor = ""
i = 0
While i < ln
t.vendor:+Chr(ReadByte(t.stream))
i:+1
Wend
' Print t.vendor
' comments
ln = ReadByte(t.stream)
ln:+ ReadByte(t.stream) Shl 8
ln:+ ReadByte(t.stream) Shl 16
ln:+ ReadByte(t.stream) Shl 24
' clear commnets list
t.comments = Null
GCCollect()
ncomments = ln
i = 0
While i < ncomments
ln = ReadByte(t.stream)
ln:+ ReadByte(t.stream) Shl 8
ln:+ ReadByte(t.stream) Shl 16
ln:+ ReadByte(t.stream) Shl 24
t.comments = t.comments:String[..i+1]
t.comments[i] = ""
j = 0
While j < ln
t.comments[i]:+Chr(ReadByte(t.stream))
j:+1
Wend
' Print t.comments[i]
i:+1
Wend
Print "header comment complete"
Return True
End Function
Function Header_ID:Int()
Local tmp:Int
If Header_Common("80") = False Return False
Print "header id found"
t.VMAJ = ReadByte(t.stream)
t.VMIN = ReadByte(t.stream)
t.VREV = ReadByte(t.stream)
t.FMBW = Read16(t.stream)
t.FMBH = Read16(t.stream)
t.PICW = Read24(t.stream) & %11111111111111111111
t.PICH = Read24(t.stream) & %11111111111111111111
t.PICX = ReadByte(t.stream)
t.PICY = ReadByte(t.stream)
t.FRN = Read32(t.stream)
t.FRD = Read32(t.stream)
t.PARN = Read24(t.stream)
t.PARD = Read24(t.stream)
t.CS = ReadByte(t.stream)
t.NOMBR = Read24(t.stream)
tmp = Read16(t.stream)
t.QUAL = (tmp & %1111110000000000) Shr 10
t.KFGSHIFT = (tmp & %0000001111100000) Shr 5
t.PF = (tmp & %0000000000011000) Shr 3
If t.PF = 1 Then Return False
If (tmp & %111) <> 0 Then Return False
Select t.PF
Case 0
t.NSBS = ((t.FMBW+1)/2)*((t.FMBH+1)/2)+2*((t.FMBW+3)/4)*((t.FMBH+3)/4)
t.NBS = 6*t.FMBW*t.FMBH
Case 2
t.NSBS = ((t.FMBW+1)/2)*((t.FMBH+1)/2)+2*((t.FMBW+3)/4)*((t.FMBH+1)/2)
t.NBS = 8*t.FMBW*t.FMBH
Case 3
t.NSBS = 3*((t.FMBW+1)/2)*((t.FMBH+1)/2)
t.NBS = 12*t.FMBW*t.FMBH
End Select
t.NMBS = t.FMBW*t.FMBH
Print "header ID complete"
Return True
End Function
Function Read32:Int(stream:TStream)
Return (ReadByte(stream) Shl 24) + (ReadByte(stream) Shl 16) + (ReadByte(stream) Shl 8) + ReadByte(stream)
End Function
Function Read16:Int(stream:TStream)
'Return (ReadByte(stream) Shl 8) + ReadByte(stream)
Local val:Int
val = ReadShort(stream)
Return ((val Shr 8) & 255) + ((val & 255) Shl 8)
End Function
Function Read24:Int(stream:TStream)
Return (ReadByte(stream) Shl 16) + (ReadByte(stream) Shl 8) + ReadByte(stream)
End Function
Function Header_Common:Int(HX:String)
If Lower(Right(Hex( ReadByte(T.stream) ),2)) <> Lower(HX) Then Return False
If peekstring(T.stream,6) <> "theora" Then Return False
Return True
End Function
Function peekstring:String(stream:TStream,length:Int)
Local i:Int
Local s:String
s = ""
i = 0
While i < length
s:+Chr(ReadByte(stream))
i:+1
Wend
Return s
End Function
|