xref: /inferno-os/appl/wm/mpeg/decode.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1implement Mpegd;
2
3include "sys.m";
4include "mpegio.m";
5
6sys: Sys;
7idct: IDCT;
8
9Mpegi, Picture, Slice, MacroBlock, YCbCr, Pair: import Mpegio;
10
11intra_tab := array[64] of {
12	8, 16, 19, 22, 26, 27, 29, 34,
13	16, 16, 22, 24, 27, 29, 34, 37,
14	19, 22, 26, 27, 29, 34, 34, 38,
15	22, 22, 26, 27, 29, 34, 37, 40,
16	22, 26, 27, 29, 32, 35, 40, 48,
17	26, 27, 29, 32, 35, 40, 48, 58,
18	26, 27, 29, 34, 38, 46, 56, 69,
19	27, 29, 35, 38, 46, 56, 69, 83,
20};
21
22nintra_tab := array[64] of { * => 16 };
23
24CLOFF: con 256;
25
26intraQ, nintraQ: array of int;
27rtmp: array of array of int;
28rflag := array[6] of int;
29rforw, dforw, rback, dback: int;
30rforw2, dforw2, rback2, dback2: int;
31ydb, ydf, cdb, cdf: int;
32vflags: int;
33past := array[3] of int;
34pinit := array[3] of { * => 128 * 8 };
35zeros := array[64] of { * => 0 };
36zeros1: array of int;
37clamp := array[CLOFF + 256 + CLOFF] of byte;
38width, height, w2, h2: int;
39mpi, mps, yadj, cadj, yskip: int;
40I, B0: ref YCbCr;
41Ps := array[2] of ref YCbCr;
42Rs := array[2] of ref YCbCr;
43P, B, R, M, N: ref YCbCr;
44pn: int = 0;
45rn: int = 0;
46
47zig := array[64] of {
48	0, 1, 8, 16, 9, 2, 3, 10, 17,
49	24, 32, 25, 18, 11, 4, 5,
50	12, 19, 26, 33, 40, 48, 41, 34,
51	27, 20, 13, 6, 7, 14, 21, 28,
52	35, 42, 49, 56, 57, 50, 43, 36,
53	29, 22, 15, 23, 30, 37, 44, 51,
54	58, 59, 52, 45, 38, 31, 39, 46,
55	53, 60, 61, 54, 47, 55, 62, 63,
56};
57
58init(m: ref Mpegi)
59{
60	sys = load Sys Sys->PATH;
61	idct = load IDCT IDCT->PATH;
62	if (idct == nil) {
63		sys->print("could not open %s: %r\n", IDCT->PATH);
64		exit;
65	}
66	idct->init();
67	width = m.width;
68	height = m.height;
69	w2 = width >> 1;
70	h2 = height >> 1;
71	mps = width >> 4;
72	mpi = mps * height >> 4;
73	yskip = 8 * width;
74	yadj = 16 * width - (width - 16);
75	cadj = 8 * w2 - (w2 - 8);
76	I = frame();
77	Ps[0] = frame();
78	Ps[1] = frame();
79	Rs[0] = Ps[0];
80	Rs[1] = Ps[1];
81	B0 = frame();
82	for (i := 0; i < CLOFF; i++)
83		clamp[i] = byte 0;
84	for (i = 0; i < 256; i++)
85		clamp[i + CLOFF] = byte i;
86	for (i = CLOFF + 256; i < CLOFF + 256 + CLOFF; i++)
87		clamp[i] = byte 255;
88	if (m.intra == nil)
89		intraQ = intra_tab;
90	else
91		intraQ = zigof(m.intra);
92	if (m.nintra == nil)
93		nintraQ = nintra_tab;
94	else
95		nintraQ = zigof(m.nintra);
96	rtmp = array[6] of array of int;
97	for (i = 0; i < 6; i++)
98		rtmp[i] = array[64] of int;
99	zeros1 = zeros[1:];
100}
101
102zarray(n: int, v: byte): array of byte
103{
104	return array[n] of { * => v };
105}
106
107frame(): ref YCbCr
108{
109	y := zarray(width * height, byte 0);
110	b := zarray(w2 * h2, byte 128);
111	r := zarray(w2 * h2, byte 128);
112	return ref YCbCr(y, b, r);
113}
114
115zigof(a: array of int): array of int
116{
117	z := array[64] of int;
118	for (i := 0; i < 64; i++)
119		z[zig[i]] = a[i];
120	return z;
121}
122
123invQ_intra(a: array of Pair, q: int, b: array of int)
124{
125	(nil, t) := a[0];
126	b[0] = t * 8;
127	b[1:] = zeros1;
128	n := 1;
129	i := 1;
130	while (n < len a) {
131		(r, l) := a[n++];
132		i += r;
133		x := zig[i++];
134		if (l > 0) {
135			v := l * q * intraQ[x] >> 3;
136			if (v > 2047)
137				b[x] = 2047;
138			else
139				b[x] = (v - 1) | 1;
140		} else {
141			v := (l * q * intraQ[x] + 7) >> 3;
142			if (v < -2048)
143				b[x] = -2048;
144			else
145				b[x] = v | 1;
146		}
147		#sys->print("%d %d %d %d\n", x, r, l, b[x]);
148	}
149}
150
151invQ_nintra(a: array of Pair, q: int, b: array of int)
152{
153	b[0:] = zeros;
154	i := 0;
155	for (n := 0; n < len a; n++) {
156		(r, l) := a[n];
157		i += r;
158		if (l == 0) {
159			raisex("zero level");
160			i++;
161			continue;
162		}
163		x := zig[i++];
164		if (l > 0) {
165			v := ((l << 1) + 1) * q * nintraQ[x] >> 4;
166			if (v > 2047)
167				b[x] = 2047;
168			else
169				b[x] = (v - 1) | 1;
170		} else {
171			v := (((l << 1) - 1) * q * nintraQ[x] + 15) >> 4;
172			if (v < -2048)
173				b[x] = -2048;
174			else
175				b[x] = v | 1;
176		}
177		#sys->print("%d %d %d %d\n", x, r, l, b[x]);
178	}
179}
180
181yzero(v: array of byte, base: int)
182{
183	x := 0;
184	i := 8;
185	do {
186		n := base;
187		j := 8;
188		do
189			v[n++] = byte 0;
190		while (--j > 0);
191		base += width;
192	} while (--i > 0);
193}
194
195czero(v: array of byte, base: int)
196{
197	x := 0;
198	i := 8;
199	do {
200		n := base;
201		j := 8;
202		do
203			v[n++] = byte 128;
204		while (--j > 0);
205		base += w2;
206	} while (--i > 0);
207
208}
209
210blockzero(d: ref YCbCr)
211{
212	yzero(d.Y, ybase);
213	yzero(d.Y, ybase + 8);
214	yzero(d.Y, ybase + yskip);
215	yzero(d.Y, ybase + 8 + yskip);
216	czero(d.Cb, cbase);
217	czero(d.Cr, cbase);
218}
219
220ydistr(a: array of int, v: array of byte, base: int)
221{
222	x := 0;
223	i := 8;
224	do {
225		n := base;
226		j := 8;
227		do
228			v[n++] = clamp[a[x++] + CLOFF];
229		while (--j > 0);
230		base += width;
231	} while (--i > 0);
232}
233
234cdistr(a: array of int, v: array of byte, base: int)
235{
236	x := 0;
237	i := 8;
238	do {
239		n := base;
240		j := 8;
241		do
242			v[n++] = clamp[a[x++] + CLOFF];
243		while (--j > 0);
244		base += w2;
245	} while (--i > 0);
246
247}
248
249invQ_intra_block(b: array of array of Pair, q: int, pred: int, d: ref YCbCr)
250{
251	a, dc: array of int;
252	if (pred)
253		dc = past;
254	else
255		dc = pinit;
256	p := dc[0];
257	for (i := 0; i < 4; i++) {
258		a = rtmp[i];
259		#sys->print("%d\n", i);
260		invQ_intra(b[i], q, a);
261		p += a[0];
262		a[0] = p;
263		#sys->print("%d\n", a[0]);
264		idct->idct(a);
265	}
266	past[0] = p;
267	for (i = 4; i < 6; i++) {
268		p = dc[i - 3];
269		a = rtmp[i];
270		#sys->print("%d\n", i);
271		invQ_intra(b[i], q, a);
272		p += a[0];
273		a[0] = p;
274		#sys->print("%d\n", a[0]);
275		past[i - 3] = p;
276		idct->idct(a);
277	}
278	ydistr(rtmp[0], d.Y, ybase);
279	ydistr(rtmp[1], d.Y, ybase + 8);
280	ydistr(rtmp[2], d.Y, ybase + yskip);
281	ydistr(rtmp[3], d.Y, ybase + 8 + yskip);
282	cdistr(rtmp[4], d.Cb, cbase);
283	cdistr(rtmp[5], d.Cr, cbase);
284}
285
286invQ_nintra_block(b: array of array of Pair, q: int)
287{
288	for (i := 0; i < 6; i++) {
289		p := b[i];
290		if (p != nil) {
291			a := rtmp[i];
292			#sys->print("%d\n", i);
293			invQ_nintra(p, q, a);
294			idct->idct(a);
295			rflag[i] = 1;
296		} else
297			rflag[i] = 0;
298	}
299}
300
301mbr, ybase, cbase: int;
302
303nextmb()
304{
305	if (--mbr == 0) {
306		ybase += yadj;
307		cbase += cadj;
308		mbr = mps;
309	} else {
310		ybase += 16;
311		cbase += 8;
312	}
313}
314
315copyblock(s, d: array of byte, b, n, w: int)
316{
317	i := 8;
318	do {
319		d[b:] = s[b:b+n];
320		b += w;
321	} while (--i > 0);
322}
323
324copyblockdisp(s, d: array of byte, b, n, w, p: int)
325{
326	i := 8;
327	p += b;
328	do {
329		d[b:] = s[p:p+n];
330		b += w;
331		p += w;
332	} while (--i > 0);
333}
334
335interpblock(s0, s1, d: array of byte, b, n, w, p0, p1: int)
336{
337	i := 8;
338	do {
339		dx := b;
340		s0x := b + p0;
341		s1x := b + p1;
342		j := n;
343		do
344			d[dx++] = byte ((int s0[s0x++] + int s1[s1x++] + 1) >> 1);
345		while (--j > 0);
346		b += w;
347	} while (--i > 0);
348}
349
350deltablock(s: array of byte, r: array of int, d: array of byte, b, w, o: int)
351{
352	rx := 0;
353	i := 8;
354	do {
355		dx := b;
356		sx := b + o;
357		j := 8;
358		do
359			d[dx++] = clamp[CLOFF + int s[sx++] + r[rx++]];
360		while (--j > 0);
361		b += w;
362	} while (--i > 0);
363}
364
365deltainterpblock(s0, s1: array of byte, r: array of int, d: array of byte, b, w, o0, o1: int)
366{
367	rx := 0;
368	i := 8;
369	do {
370		dx := b;
371		s0x := b + o0;
372		s1x := b + o1;
373		j := 8;
374		do
375			d[dx++] = clamp[CLOFF + ((int s0[s0x++] + int s1[s1x++] + 1) >> 1) + r[rx++]];
376		while (--j > 0);
377		b += w;
378	} while (--i > 0);
379}
380
381dispblock(s, d: array of byte, n, b, w, o: int)
382{
383	if (rflag[n])
384		deltablock(s, rtmp[n], d, b, w, o);
385	else
386		copyblockdisp(s, d, b, 8, w, o);
387}
388
389genblock(s0, s1, d: array of byte, n, b, w, o0, o1: int)
390{
391	if (rflag[n])
392		deltainterpblock(s0, s1, rtmp[n], d, b, w, o0, o1);
393	else
394		interpblock(s0, s1, d, b, 8, w, o0, o1);
395}
396
397copymb()
398{
399	copyblock(R.Y, P.Y, ybase, 16, width);
400	copyblock(R.Y, P.Y, ybase + yskip, 16, width);
401	copyblock(R.Cb, P.Cb, cbase, 8, w2);
402	copyblock(R.Cr, P.Cr, cbase, 8, w2);
403}
404
405deltamb()
406{
407	dispblock(R.Y, P.Y, 0, ybase, width, 0);
408	dispblock(R.Y, P.Y, 1, ybase + 8, width, 0);
409	dispblock(R.Y, P.Y, 2, ybase + yskip, width, 0);
410	dispblock(R.Y, P.Y, 3, ybase + 8 + yskip, width, 0);
411	dispblock(R.Cb, P.Cb, 4, cbase, w2, 0);
412	dispblock(R.Cr, P.Cr, 5, cbase, w2, 0);
413}
414
415copymbforw()
416{
417	copyblockdisp(N.Y, B.Y, ybase, 16, width, ydf);
418	copyblockdisp(N.Y, B.Y, ybase + yskip, 16, width, ydf);
419	copyblockdisp(N.Cb, B.Cb, cbase, 8, w2, cdf);
420	copyblockdisp(N.Cr, B.Cr, cbase, 8, w2, cdf);
421}
422
423copymbback()
424{
425	copyblockdisp(M.Y, B.Y, ybase, 16, width, ydb);
426	copyblockdisp(M.Y, B.Y, ybase + yskip, 16, width, ydb);
427	copyblockdisp(M.Cb, B.Cb, cbase, 8, w2, cdb);
428	copyblockdisp(M.Cr, B.Cr, cbase, 8, w2, cdb);
429}
430
431copymbbackforw()
432{
433	interpblock(M.Y, N.Y, B.Y, ybase, 16, width, ydb, ydf);
434	interpblock(M.Y, N.Y, B.Y, ybase + yskip, 16, width, ydb, ydf);
435	interpblock(M.Cb, N.Cb, B.Cb, cbase, 8, w2, cdb, cdf);
436	interpblock(M.Cr, N.Cr, B.Cr, cbase, 8, w2, cdb, cdf);
437}
438
439deltambforw()
440{
441	dispblock(N.Y, B.Y, 0, ybase, width, ydf);
442	dispblock(N.Y, B.Y, 1, ybase + 8, width, ydf);
443	dispblock(N.Y, B.Y, 2, ybase + yskip, width, ydf);
444	dispblock(N.Y, B.Y, 3, ybase + 8 + yskip, width, ydf);
445	dispblock(N.Cb, B.Cb, 4, cbase, w2, cdf);
446	dispblock(N.Cr, B.Cr, 5, cbase, w2, cdf);
447}
448
449deltambback()
450{
451	dispblock(M.Y, B.Y, 0, ybase, width, ydb);
452	dispblock(M.Y, B.Y, 1, ybase + 8, width, ydb);
453	dispblock(M.Y, B.Y, 2, ybase + yskip, width, ydb);
454	dispblock(M.Y, B.Y, 3, ybase + 8 + yskip, width, ydb);
455	dispblock(M.Cb, B.Cb, 4, cbase, w2, cdb);
456	dispblock(M.Cr, B.Cr, 5, cbase, w2, cdb);
457}
458
459deltambbackforw()
460{
461	genblock(M.Y, N.Y, B.Y, 0, ybase, width, ydb, ydf);
462	genblock(M.Y, N.Y, B.Y, 1, ybase + 8, width, ydb, ydf);
463	genblock(M.Y, N.Y, B.Y, 2, ybase + yskip, width, ydb, ydf);
464	genblock(M.Y, N.Y, B.Y, 3, ybase + 8 + yskip, width, ydb, ydf);
465	genblock(M.Cb, N.Cb, B.Cb, 4, cbase, w2, cdb, cdf);
466	genblock(M.Cr, N.Cr, B.Cr, 5, cbase, w2, cdb, cdf);
467}
468
469deltambinterp()
470{
471	case vflags & (Mpegio->MB_MF | Mpegio->MB_MB) {
472	Mpegio->MB_MF =>
473		deltambforw();
474	Mpegio->MB_MB =>
475		deltambback();
476	Mpegio->MB_MF | Mpegio->MB_MB =>
477		deltambbackforw();
478	* =>
479		raisex("bad vflags");
480	}
481}
482
483interpmb()
484{
485	case vflags & (Mpegio->MB_MF | Mpegio->MB_MB) {
486	Mpegio->MB_MF =>
487		copymbforw();
488	Mpegio->MB_MB =>
489		copymbback();
490	Mpegio->MB_MF | Mpegio->MB_MB =>
491		copymbbackforw();
492	* =>
493		raisex("bad vflags");
494	}
495}
496
497Idecode(p: ref Picture): ref YCbCr
498{
499	sa := p.slices;
500	n := 0;
501	mbr = mps;
502	ybase = 0;
503	cbase = 0;
504	for (i := 0; i < len sa; i++) {
505		pred := 0;
506		ba := sa[i].blocks;
507		for (j := 0; j < len ba; j++) {
508			invQ_intra_block(ba[j].rls, ba[j].qscale, pred, I);
509			nextmb();
510			n++;
511			pred = 1;
512		}
513	}
514	if (n != mpi)
515		raisex("I mb count");
516	R = I;
517	Rs[rn] = I;
518	rn ^= 1;
519	return I;
520}
521
522Pdecode(p: ref Picture): ref YCbCr
523{
524	rforwp, dforwp: int;
525	md, c: int;
526	P = Ps[pn];
527	N = R;
528	B = P;
529	pn ^= 1;
530	fs := 1 << p.forwfc;
531	fsr := fs << 5;
532	fsmin := -(fs << 4);
533	fsmax := (fs << 4) - 1;
534	sa := p.slices;
535	n := 0;
536	mbr = mps;
537	ybase = 0;
538	cbase = 0;
539	for (i := 0; i < len sa; i++) {
540		pred := 0;
541		ipred := 0;
542		ba := sa[i].blocks;
543		for (j := 0; j < len ba; j++) {
544			mb := ba[j];
545			while (n < mb.addr) {
546				copymb();
547				ipred = 0;
548				pred = 0;
549				nextmb();
550				n++;
551			}
552			if (mb.flags & Mpegio->MB_I) {
553				invQ_intra_block(mb.rls, mb.qscale, ipred, P);
554				#blockzero(P);
555				ipred = 1;
556				pred = 0;
557			} else {
558				if (mb.flags & Mpegio->MB_MF) {
559					if (fs == 1 || mb.mhfc == 0)
560						md = mb.mhfc;
561					else if ((c = mb.mhfc) < 0)
562						md = (c + 1) * fs - mb.mhfr - 1;
563					else
564						md = (c - 1) * fs + mb.mhfr + 1;
565					if (pred)
566						md += rforwp;
567					if (md > fsmax)
568						rforw = md - fsr;
569					else if (md < fsmin)
570						rforw = md + fsr;
571					else
572						rforw = md;
573					rforwp = rforw;
574					if (fs == 1 || mb.mvfc == 0)
575						md = mb.mvfc;
576					else if ((c = mb.mvfc) < 0)
577						md = (c + 1) * fs - mb.mvfr - 1;
578					else
579						md = (c - 1) * fs + mb.mvfr + 1;
580					if (pred)
581						md += dforwp;
582					if (md > fsmax)
583						dforw = md - fsr;
584					else if (md < fsmin)
585						dforw = md + fsr;
586					else
587						dforw = md;
588					dforwp = dforw;
589					if (p.flags & Mpegio->FPFV) {
590						rforw2 = rforw;
591						dforw2 = dforw;
592						rforw <<= 1;
593						dforw <<= 1;
594						ydf = rforw2 + dforw2 * width;
595						cdf = (rforw2 >> 1) + (dforw2 >> 1) * w2;
596					} else {
597						if (rforw < 0)
598							rforw2 = (rforw + 1) >> 1;
599						else
600							rforw2 = rforw >> 1;
601						if (dforw < 0)
602							dforw2 = (dforw + 1) >> 1;
603						else
604							dforw2 = dforw >> 1;
605						ydf = (rforw >> 1) + (dforw >> 1) * width;
606						cdf = (rforw2 >> 1) + (dforw2 >> 1) * w2;
607					}
608					pred = 1;
609					if (mb.rls != nil) {
610						invQ_nintra_block(mb.rls, mb.qscale);
611						deltambforw();
612					} else
613						copymbforw();
614				} else {
615					if (mb.rls == nil)
616						raisex("empty delta");
617					invQ_nintra_block(mb.rls, mb.qscale);
618					deltamb();
619					pred = 0;
620				}
621				ipred = 0;
622			}
623			nextmb();
624			n++;
625		}
626	}
627	while (n < mpi) {
628		copymb();
629		nextmb();
630		n++;
631	}
632	R = P;
633	Rs[rn] = P;
634	rn ^= 1;
635	return P;
636}
637
638Bdecode(p: ref Mpegio->Picture): ref Mpegio->YCbCr
639{
640	return Bdecode2(p, Rs[rn ^ 1], Rs[rn]);
641}
642
643Bdecode2(p: ref Mpegio->Picture, f0, f1: ref Mpegio->YCbCr): ref Mpegio->YCbCr
644{
645	rforwp, dforwp, rbackp, dbackp: int;
646	md, c: int;
647	M = f0;
648	N = f1;
649	B = B0;
650	fs := 1 << p.forwfc;
651	fsr := fs << 5;
652	fsmin := -(fs << 4);
653	fsmax := (fs << 4) - 1;
654	bs := 1 << p.backfc;
655	bsr := bs << 5;
656	bsmin := -(bs << 4);
657	bsmax := (bs << 4) - 1;
658	sa := p.slices;
659	n := 0;
660	mbr = mps;
661	ybase = 0;
662	cbase = 0;
663	for (i := 0; i < len sa; i++) {
664		ipred := 0;
665		rback = 0;
666		rforw = 0;
667		dback = 0;
668		dforw = 0;
669		rbackp = 0;
670		rforwp = 0;
671		dbackp = 0;
672		dforwp = 0;
673		rback2 = 0;
674		rforw2 = 0;
675		dback2 = 0;
676		dforw2 = 0;
677		ydb = 0;
678		ydf = 0;
679		cdb = 0;
680		cdf = 0;
681		ba := sa[i].blocks;
682		for (j := 0; j < len ba; j++) {
683			mb := ba[j];
684			while (n < mb.addr) {
685				interpmb();
686				nextmb();
687				ipred = 0;
688				n++;
689			}
690			if (mb.flags & Mpegio->MB_I) {
691				invQ_intra_block(mb.rls, mb.qscale, ipred, B);
692				ipred = 1;
693				rback = 0;
694				rforw = 0;
695				dback = 0;
696				dforw = 0;
697				rbackp = 0;
698				rforwp = 0;
699				dbackp = 0;
700				dforwp = 0;
701				rback2 = 0;
702				rforw2 = 0;
703				dback2 = 0;
704				dforw2 = 0;
705				ydb = 0;
706				ydf = 0;
707				cdb = 0;
708				cdf = 0;
709			} else {
710				if (mb.flags & Mpegio->MB_MF) {
711					if (fs == 1 || mb.mhfc == 0)
712						md = mb.mhfc;
713					else if ((c = mb.mhfc) < 0)
714						md = (c + 1) * fs - mb.mhfr - 1;
715					else
716						md = (c - 1) * fs + mb.mhfr + 1;
717					md += rforwp;
718					if (md > fsmax)
719						rforw = md - fsr;
720					else if (md < fsmin)
721						rforw = md + fsr;
722					else
723						rforw = md;
724					rforwp = rforw;
725					if (fs == 1 || mb.mvfc == 0)
726						md = mb.mvfc;
727					else if ((c = mb.mvfc) < 0)
728						md = (c + 1) * fs - mb.mvfr - 1;
729					else
730						md = (c - 1) * fs + mb.mvfr + 1;
731					md += dforwp;
732					if (md > fsmax)
733						dforw = md - fsr;
734					else if (md < fsmin)
735						dforw = md + fsr;
736					else
737						dforw = md;
738					dforwp = dforw;
739					if (p.flags & Mpegio->FPFV) {
740						rforw2 = rforw;
741						dforw2 = dforw;
742						rforw <<= 1;
743						dforw <<= 1;
744						ydf = rforw2 + dforw2 * width;
745						cdf = (rforw2 >> 1) + (dforw2 >> 1) * w2;
746					} else {
747						if (rforw < 0)
748							rforw2 = (rforw + 1) >> 1;
749						else
750							rforw2 = rforw >> 1;
751						if (dforw < 0)
752							dforw2 = (dforw + 1) >> 1;
753						else
754							dforw2 = dforw >> 1;
755						ydf = (rforw >> 1) + (dforw >> 1) * width;
756						cdf = (rforw2 >> 1) + (dforw2 >> 1) * w2;
757					}
758				}
759				if (mb.flags & Mpegio->MB_MB) {
760					if (bs == 1 || mb.mhbc == 0)
761						md = mb.mhbc;
762					else if ((c = mb.mhbc) < 0)
763						md = (c + 1) * bs - mb.mhbr - 1;
764					else
765						md = (c - 1) * bs + mb.mhbr + 1;
766					md += rbackp;
767					if (md > bsmax)
768						rback = md - bsr;
769					else if (md < bsmin)
770						rback = md + bsr;
771					else
772						rback = md;
773					rbackp = rback;
774					if (bs == 1 || mb.mvbc == 0)
775						md = mb.mvbc;
776					else if ((c = mb.mvbc) < 0)
777						md = (c + 1) * bs - mb.mvbr - 1;
778					else
779						md = (c - 1) * bs + mb.mvbr + 1;
780					md += dbackp;
781					if (md > bsmax)
782						dback = md - bsr;
783					else if (md < bsmin)
784						dback = md + bsr;
785					else
786						dback = md;
787					dbackp = dback;
788					if (p.flags & Mpegio->FPBV) {
789						rback2 = rback;
790						dback2 = dback;
791						rback <<= 1;
792						dback <<= 1;
793						ydb = rback2 + dback2 * width;
794						cdb = (rback2 >> 1) + (dback2 >> 1) * w2;
795					} else {
796						if (rback < 0)
797							rback2 = (rback + 1) >> 1;
798						else
799							rback2 = rback >> 1;
800						if (dback < 0)
801							dback2 = (dback + 1) >> 1;
802						else
803							dback2 = dback >> 1;
804						ydb = (rback >> 1) + (dback >> 1) * width;
805						cdb = (rback2 >> 1) + (dback2 >> 1) * w2;
806					}
807				}
808				vflags = mb.flags;
809				if (mb.rls != nil) {
810					invQ_nintra_block(mb.rls, mb.qscale);
811					deltambinterp();
812				} else
813					interpmb();
814				ipred = 0;
815			}
816			nextmb();
817			n++;
818		}
819	}
820	while (n < mpi) {
821		interpmb();
822		nextmb();
823		n++;
824	}
825	return B;
826}
827
828raisex(nil: string)
829{
830	raise "decode error";
831}
832