1*37da2899SCharles.Forsythimplement QuickTime; 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsythinclude "sys.m"; 4*37da2899SCharles.Forsyth 5*37da2899SCharles.Forsythsys: Sys; 6*37da2899SCharles.Forsyth 7*37da2899SCharles.Forsythinclude "quicktime.m"; 8*37da2899SCharles.Forsyth 9*37da2899SCharles.Forsythinit() 10*37da2899SCharles.Forsyth{ 11*37da2899SCharles.Forsyth sys = load Sys Sys->PATH; 12*37da2899SCharles.Forsyth} 13*37da2899SCharles.Forsyth 14*37da2899SCharles.Forsythopen(file: string): (ref QD, string) 15*37da2899SCharles.Forsyth{ 16*37da2899SCharles.Forsyth fd := sys->open(file, sys->OREAD); 17*37da2899SCharles.Forsyth if(fd == nil) 18*37da2899SCharles.Forsyth return (nil, "open failed"); 19*37da2899SCharles.Forsyth 20*37da2899SCharles.Forsyth r := ref QD; 21*37da2899SCharles.Forsyth r.fd = fd; 22*37da2899SCharles.Forsyth r.buf = array[DEFBUF] of byte; 23*37da2899SCharles.Forsyth 24*37da2899SCharles.Forsyth (hdr, l) := r.atomhdr(); 25*37da2899SCharles.Forsyth if(hdr != "mdat") 26*37da2899SCharles.Forsyth return (nil, "not a QuickTime movie file"); 27*37da2899SCharles.Forsyth 28*37da2899SCharles.Forsyth # 29*37da2899SCharles.Forsyth # We are expecting a unified file with .data then .rsrc 30*37da2899SCharles.Forsyth # 31*37da2899SCharles.Forsyth r.skipatom(l); 32*37da2899SCharles.Forsyth 33*37da2899SCharles.Forsyth return (r, nil); 34*37da2899SCharles.Forsyth} 35*37da2899SCharles.Forsyth 36*37da2899SCharles.ForsythQD.atomhdr(r: self ref QD): (string, int) 37*37da2899SCharles.Forsyth{ 38*37da2899SCharles.Forsyth b := array[8] of byte; 39*37da2899SCharles.Forsyth 40*37da2899SCharles.Forsyth if(r.readn(b, 8) != 8) 41*37da2899SCharles.Forsyth return (nil, -1); 42*37da2899SCharles.Forsyth 43*37da2899SCharles.Forsythfor(i := 0; i < 8; i++) 44*37da2899SCharles.Forsythsys->print("%.2ux ", int b[i]); 45*37da2899SCharles.Forsythsys->print(" %s %d\n", string b[4:8], bedword(b, 0)); 46*37da2899SCharles.Forsyth 47*37da2899SCharles.Forsyth return (string b[4:8], bedword(b, 0)); 48*37da2899SCharles.Forsyth} 49*37da2899SCharles.Forsyth 50*37da2899SCharles.ForsythQD.skipatom(r: self ref QD, l: int): int 51*37da2899SCharles.Forsyth{ 52*37da2899SCharles.Forsyth return r.skip(l - AtomHDR); 53*37da2899SCharles.Forsyth} 54*37da2899SCharles.Forsyth 55*37da2899SCharles.ForsythQD.mvhd(q: self ref QD, l: int): string 56*37da2899SCharles.Forsyth{ 57*37da2899SCharles.Forsyth l -= AtomHDR; 58*37da2899SCharles.Forsyth if(l != MvhdrSIZE) 59*37da2899SCharles.Forsyth return "mvhd atom funny size"; 60*37da2899SCharles.Forsyth 61*37da2899SCharles.Forsyth b := array[l] of byte; 62*37da2899SCharles.Forsyth if(q.readn(b, l) != l) 63*37da2899SCharles.Forsyth return "short read in mvhd"; 64*37da2899SCharles.Forsyth 65*37da2899SCharles.Forsyth mvhdr := ref Mvhdr; 66*37da2899SCharles.Forsyth 67*37da2899SCharles.Forsyth mvhdr.version = bedword(b, 0); 68*37da2899SCharles.Forsyth mvhdr.create = bedword(b, 4); 69*37da2899SCharles.Forsyth mvhdr.modtime = bedword(b, 8); 70*37da2899SCharles.Forsyth mvhdr.timescale = bedword(b, 12); 71*37da2899SCharles.Forsyth mvhdr.duration = bedword(b, 16); 72*37da2899SCharles.Forsyth mvhdr.rate = bedword(b, 20); 73*37da2899SCharles.Forsyth mvhdr.vol = beword(b, 24); 74*37da2899SCharles.Forsyth mvhdr.r1 = bedword(b, 26); 75*37da2899SCharles.Forsyth mvhdr.r2 = bedword(b, 30); 76*37da2899SCharles.Forsyth 77*37da2899SCharles.Forsyth mvhdr.matrix = array[9] of int; 78*37da2899SCharles.Forsyth for(i :=0; i<9; i++) 79*37da2899SCharles.Forsyth mvhdr.matrix[i] = bedword(b, 34+i*4); 80*37da2899SCharles.Forsyth 81*37da2899SCharles.Forsyth mvhdr.r3 = beword(b, 70); 82*37da2899SCharles.Forsyth mvhdr.r4 = bedword(b, 72); 83*37da2899SCharles.Forsyth mvhdr.pvtime = bedword(b, 76); 84*37da2899SCharles.Forsyth mvhdr.posttime = bedword(b, 80); 85*37da2899SCharles.Forsyth mvhdr.seltime = bedword(b, 84); 86*37da2899SCharles.Forsyth mvhdr.seldurat = bedword(b, 88); 87*37da2899SCharles.Forsyth mvhdr.curtime = bedword(b, 92); 88*37da2899SCharles.Forsyth mvhdr.nxttkid = bedword(b, 96); 89*37da2899SCharles.Forsyth 90*37da2899SCharles.Forsyth q.mvhdr = mvhdr; 91*37da2899SCharles.Forsyth return nil; 92*37da2899SCharles.Forsyth} 93*37da2899SCharles.Forsyth 94*37da2899SCharles.ForsythQD.trak(q: self ref QD, l: int): string 95*37da2899SCharles.Forsyth{ 96*37da2899SCharles.Forsyth (tk, tkl) := q.atomhdr(); 97*37da2899SCharles.Forsyth if(tk != "tkhd") 98*37da2899SCharles.Forsyth return "missing track header atom"; 99*37da2899SCharles.Forsyth 100*37da2899SCharles.Forsyth l -= tkl; 101*37da2899SCharles.Forsyth tkl -= AtomHDR; 102*37da2899SCharles.Forsyth b := array[tkl] of byte; 103*37da2899SCharles.Forsyth if(q.readn(b, tkl) != tkl) 104*37da2899SCharles.Forsyth return "short read in tkhd"; 105*37da2899SCharles.Forsyth 106*37da2899SCharles.Forsyth tkhdr := ref Tkhdr; 107*37da2899SCharles.Forsyth 108*37da2899SCharles.Forsyth tkhdr.version = bedword(b, 0); 109*37da2899SCharles.Forsyth tkhdr.creation = bedword(b, 4); 110*37da2899SCharles.Forsyth tkhdr.modtime = bedword(b, 8); 111*37da2899SCharles.Forsyth tkhdr.trackid = bedword(b, 12); 112*37da2899SCharles.Forsyth tkhdr.timescale = bedword(b, 16); 113*37da2899SCharles.Forsyth tkhdr.duration = bedword(b, 20); 114*37da2899SCharles.Forsyth tkhdr.timeoff = bedword(b, 24); 115*37da2899SCharles.Forsyth tkhdr.priority = bedword(b, 28); 116*37da2899SCharles.Forsyth tkhdr.layer = beword(b, 32); 117*37da2899SCharles.Forsyth tkhdr.altgrp = beword(b, 34); 118*37da2899SCharles.Forsyth tkhdr.volume = beword(b, 36); 119*37da2899SCharles.Forsyth 120*37da2899SCharles.Forsyth tkhdr.matrix = array[9] of int; 121*37da2899SCharles.Forsyth for(i := 0; i < 9; i++) 122*37da2899SCharles.Forsyth tkhdr.matrix[i] = bedword(b, 38+i*4); 123*37da2899SCharles.Forsyth 124*37da2899SCharles.Forsyth tkhdr.width = bedword(b, 74); 125*37da2899SCharles.Forsyth tkhdr.height = bedword(b, 78); 126*37da2899SCharles.Forsyth 127*37da2899SCharles.Forsyth (md, mdl) := q.atomhdr(); 128*37da2899SCharles.Forsyth if(md != "mdia") 129*37da2899SCharles.Forsyth return "missing media atom"; 130*37da2899SCharles.Forsyth 131*37da2899SCharles.Forsyth while(mdl != AtomHDR) { 132*37da2899SCharles.Forsyth (atom, atoml) := q.atomhdr(); 133*37da2899SCharles.Forsythsys->print("\t%s %d\n", atom, atoml); 134*37da2899SCharles.Forsyth q.skipatom(atoml); 135*37da2899SCharles.Forsyth 136*37da2899SCharles.Forsyth mdl -= atoml; 137*37da2899SCharles.Forsyth } 138*37da2899SCharles.Forsyth 139*37da2899SCharles.Forsyth return nil; 140*37da2899SCharles.Forsyth} 141*37da2899SCharles.Forsyth 142*37da2899SCharles.ForsythQD.readn(r: self ref QD, b: array of byte, l: int): int 143*37da2899SCharles.Forsyth{ 144*37da2899SCharles.Forsyth if(r.nbyte < l) { 145*37da2899SCharles.Forsyth c := 0; 146*37da2899SCharles.Forsyth if(r.nbyte != 0) { 147*37da2899SCharles.Forsyth b[0:] = r.buf[r.ptr:]; 148*37da2899SCharles.Forsyth l -= r.nbyte; 149*37da2899SCharles.Forsyth c += r.nbyte; 150*37da2899SCharles.Forsyth b = b[r.nbyte:]; 151*37da2899SCharles.Forsyth } 152*37da2899SCharles.Forsyth bsize := len r.buf; 153*37da2899SCharles.Forsyth while(l != 0) { 154*37da2899SCharles.Forsyth r.nbyte = sys->read(r.fd, r.buf, bsize); 155*37da2899SCharles.Forsyth if(r.nbyte <= 0) { 156*37da2899SCharles.Forsyth r.nbyte = 0; 157*37da2899SCharles.Forsyth return -1; 158*37da2899SCharles.Forsyth } 159*37da2899SCharles.Forsyth n := l; 160*37da2899SCharles.Forsyth if(n > bsize) 161*37da2899SCharles.Forsyth n = bsize; 162*37da2899SCharles.Forsyth 163*37da2899SCharles.Forsyth r.ptr = 0; 164*37da2899SCharles.Forsyth b[0:] = r.buf[0:n]; 165*37da2899SCharles.Forsyth b = b[n:]; 166*37da2899SCharles.Forsyth r.nbyte -= n; 167*37da2899SCharles.Forsyth r.ptr += n; 168*37da2899SCharles.Forsyth l -= n; 169*37da2899SCharles.Forsyth c += n; 170*37da2899SCharles.Forsyth } 171*37da2899SCharles.Forsyth return c; 172*37da2899SCharles.Forsyth } 173*37da2899SCharles.Forsyth b[0:] = r.buf[r.ptr:r.ptr+l]; 174*37da2899SCharles.Forsyth r.nbyte -= l; 175*37da2899SCharles.Forsyth r.ptr += l; 176*37da2899SCharles.Forsyth return l; 177*37da2899SCharles.Forsyth} 178*37da2899SCharles.Forsyth 179*37da2899SCharles.ForsythQD.skip(r: self ref QD, size: int): int 180*37da2899SCharles.Forsyth{ 181*37da2899SCharles.Forsyth if(r.nbyte != 0) { 182*37da2899SCharles.Forsyth n := size; 183*37da2899SCharles.Forsyth if(n > r.nbyte) 184*37da2899SCharles.Forsyth n = r.nbyte; 185*37da2899SCharles.Forsyth r.ptr += n; 186*37da2899SCharles.Forsyth r.nbyte -= n; 187*37da2899SCharles.Forsyth size -= n; 188*37da2899SCharles.Forsyth if(size == 0) 189*37da2899SCharles.Forsyth return 0; 190*37da2899SCharles.Forsyth } 191*37da2899SCharles.Forsyth return int sys->seek(r.fd, big size, sys->SEEKRELA); 192*37da2899SCharles.Forsyth} 193*37da2899SCharles.Forsyth 194*37da2899SCharles.Forsythbeword(b: array of byte, o: int): int 195*37da2899SCharles.Forsyth{ 196*37da2899SCharles.Forsyth return (int b[o] << 8) | int b[o+1]; 197*37da2899SCharles.Forsyth} 198*37da2899SCharles.Forsyth 199*37da2899SCharles.Forsythbedword(b: array of byte, o: int): int 200*37da2899SCharles.Forsyth{ 201*37da2899SCharles.Forsyth return (int b[o] << 24) | 202*37da2899SCharles.Forsyth (int b[o+1] << 16) | 203*37da2899SCharles.Forsyth (int b[o+2] << 8) | 204*37da2899SCharles.Forsyth int b[o+3]; 205*37da2899SCharles.Forsyth} 206