diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/lib/quicktime.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/lib/quicktime.b')
| -rw-r--r-- | appl/lib/quicktime.b | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/appl/lib/quicktime.b b/appl/lib/quicktime.b new file mode 100644 index 00000000..4163c578 --- /dev/null +++ b/appl/lib/quicktime.b @@ -0,0 +1,205 @@ +implement QuickTime; + +include "sys.m"; + +sys: Sys; + +include "quicktime.m"; + +init() +{ + sys = load Sys Sys->PATH; +} + +open(file: string): (ref QD, string) +{ + fd := sys->open(file, sys->OREAD); + if(fd == nil) + return (nil, "open failed"); + + r := ref QD; + r.fd = fd; + r.buf = array[DEFBUF] of byte; + + (hdr, l) := r.atomhdr(); + if(hdr != "mdat") + return (nil, "not a QuickTime movie file"); + + # + # We are expecting a unified file with .data then .rsrc + # + r.skipatom(l); + + return (r, nil); +} + +QD.atomhdr(r: self ref QD): (string, int) +{ + b := array[8] of byte; + + if(r.readn(b, 8) != 8) + return (nil, -1); + +for(i := 0; i < 8; i++) +sys->print("%.2ux ", int b[i]); +sys->print(" %s %d\n", string b[4:8], bedword(b, 0)); + + return (string b[4:8], bedword(b, 0)); +} + +QD.skipatom(r: self ref QD, l: int): int +{ + return r.skip(l - AtomHDR); +} + +QD.mvhd(q: self ref QD, l: int): string +{ + l -= AtomHDR; + if(l != MvhdrSIZE) + return "mvhd atom funny size"; + + b := array[l] of byte; + if(q.readn(b, l) != l) + return "short read in mvhd"; + + mvhdr := ref Mvhdr; + + mvhdr.version = bedword(b, 0); + mvhdr.create = bedword(b, 4); + mvhdr.modtime = bedword(b, 8); + mvhdr.timescale = bedword(b, 12); + mvhdr.duration = bedword(b, 16); + mvhdr.rate = bedword(b, 20); + mvhdr.vol = beword(b, 24); + mvhdr.r1 = bedword(b, 26); + mvhdr.r2 = bedword(b, 30); + + mvhdr.matrix = array[9] of int; + for(i :=0; i<9; i++) + mvhdr.matrix[i] = bedword(b, 34+i*4); + + mvhdr.r3 = beword(b, 70); + mvhdr.r4 = bedword(b, 72); + mvhdr.pvtime = bedword(b, 76); + mvhdr.posttime = bedword(b, 80); + mvhdr.seltime = bedword(b, 84); + mvhdr.seldurat = bedword(b, 88); + mvhdr.curtime = bedword(b, 92); + mvhdr.nxttkid = bedword(b, 96); + + q.mvhdr = mvhdr; + return nil; +} + +QD.trak(q: self ref QD, l: int): string +{ + (tk, tkl) := q.atomhdr(); + if(tk != "tkhd") + return "missing track header atom"; + + l -= tkl; + tkl -= AtomHDR; + b := array[tkl] of byte; + if(q.readn(b, tkl) != tkl) + return "short read in tkhd"; + + tkhdr := ref Tkhdr; + + tkhdr.version = bedword(b, 0); + tkhdr.creation = bedword(b, 4); + tkhdr.modtime = bedword(b, 8); + tkhdr.trackid = bedword(b, 12); + tkhdr.timescale = bedword(b, 16); + tkhdr.duration = bedword(b, 20); + tkhdr.timeoff = bedword(b, 24); + tkhdr.priority = bedword(b, 28); + tkhdr.layer = beword(b, 32); + tkhdr.altgrp = beword(b, 34); + tkhdr.volume = beword(b, 36); + + tkhdr.matrix = array[9] of int; + for(i := 0; i < 9; i++) + tkhdr.matrix[i] = bedword(b, 38+i*4); + + tkhdr.width = bedword(b, 74); + tkhdr.height = bedword(b, 78); + + (md, mdl) := q.atomhdr(); + if(md != "mdia") + return "missing media atom"; + + while(mdl != AtomHDR) { + (atom, atoml) := q.atomhdr(); +sys->print("\t%s %d\n", atom, atoml); + q.skipatom(atoml); + + mdl -= atoml; + } + + return nil; +} + +QD.readn(r: self ref QD, b: array of byte, l: int): int +{ + if(r.nbyte < l) { + c := 0; + if(r.nbyte != 0) { + b[0:] = r.buf[r.ptr:]; + l -= r.nbyte; + c += r.nbyte; + b = b[r.nbyte:]; + } + bsize := len r.buf; + while(l != 0) { + r.nbyte = sys->read(r.fd, r.buf, bsize); + if(r.nbyte <= 0) { + r.nbyte = 0; + return -1; + } + n := l; + if(n > bsize) + n = bsize; + + r.ptr = 0; + b[0:] = r.buf[0:n]; + b = b[n:]; + r.nbyte -= n; + r.ptr += n; + l -= n; + c += n; + } + return c; + } + b[0:] = r.buf[r.ptr:r.ptr+l]; + r.nbyte -= l; + r.ptr += l; + return l; +} + +QD.skip(r: self ref QD, size: int): int +{ + if(r.nbyte != 0) { + n := size; + if(n > r.nbyte) + n = r.nbyte; + r.ptr += n; + r.nbyte -= n; + size -= n; + if(size == 0) + return 0; + } + return int sys->seek(r.fd, big size, sys->SEEKRELA); +} + +beword(b: array of byte, o: int): int +{ + return (int b[o] << 8) | int b[o+1]; +} + +bedword(b: array of byte, o: int): int +{ + return (int b[o] << 24) | + (int b[o+1] << 16) | + (int b[o+2] << 8) | + int b[o+3]; +} |
