summaryrefslogtreecommitdiff
path: root/appl/lib/quicktime.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/lib/quicktime.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/lib/quicktime.b')
-rw-r--r--appl/lib/quicktime.b205
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];
+}