xref: /inferno-os/appl/lib/quicktime.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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