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