forsyth20121205-174063a80cc13 years agoHistory
831 lines · 16.0 KB · Brainfuck
RawDownload
implement Mpegd; include "sys.m";include "mpegio.m"; sys: Sys;idct: IDCT; Mpegi, Picture, Slice, MacroBlock, YCbCr, Pair: import Mpegio; intra_tab := array[64] of {	8, 16, 19, 22, 26, 27, 29, 34,	16, 16, 22, 24, 27, 29, 34, 37,	19, 22, 26, 27, 29, 34, 34, 38,	22, 22, 26, 27, 29, 34, 37, 40,	22, 26, 27, 29, 32, 35, 40, 48,	26, 27, 29, 32, 35, 40, 48, 58,	26, 27, 29, 34, 38, 46, 56, 69,	27, 29, 35, 38, 46, 56, 69, 83,}; nintra_tab := array[64] of { * => 16 }; CLOFF: con 256; intraQ, nintraQ: array of int;rtmp: array of array of int;rflag := array[6] of int;rforw, dforw, rback, dback: int;rforw2, dforw2, rback2, dback2: int;ydb, ydf, cdb, cdf: int;vflags: int;past := array[3] of int;pinit := array[3] of { * => 128 * 8 };zeros := array[64] of { * => 0 };zeros1: array of int;clamp := array[CLOFF + 256 + CLOFF] of byte;width, height, w2, h2: int;mpi, mps, yadj, cadj, yskip: int;I, B0: ref YCbCr;Ps := array[2] of ref YCbCr;Rs := array[2] of ref YCbCr;P, B, R, M, N: ref YCbCr;pn: int = 0;rn: int = 0; zig := array[64] of {	0, 1, 8, 16, 9, 2, 3, 10, 17,	24, 32, 25, 18, 11, 4, 5,	12, 19, 26, 33, 40, 48, 41, 34,	27, 20, 13, 6, 7, 14, 21, 28, 	35, 42, 49, 56, 57, 50, 43, 36,	29, 22, 15, 23, 30, 37, 44, 51,	58, 59, 52, 45, 38, 31, 39, 46,	53, 60, 61, 54, 47, 55, 62, 63,}; init(m: ref Mpegi){	sys = load Sys Sys->PATH;	idct = load IDCT IDCT->PATH;	if (idct == nil) {		sys->print("could not open %s: %r\n", IDCT->PATH);		exit;	}	idct->init();	width = m.width;	height = m.height;	w2 = width >> 1;	h2 = height >> 1;	mps = width >> 4;	mpi = mps * height >> 4;	yskip = 8 * width;	yadj = 16 * width - (width - 16);	cadj = 8 * w2 - (w2 - 8);	I = frame();	Ps[0] = frame();	Ps[1] = frame();	Rs[0] = Ps[0];	Rs[1] = Ps[1];	B0 = frame();	for (i := 0; i < CLOFF; i++)		clamp[i] = byte 0;	for (i = 0; i < 256; i++)		clamp[i + CLOFF] = byte i;	for (i = CLOFF + 256; i < CLOFF + 256 + CLOFF; i++)		clamp[i] = byte 255;	if (m.intra == nil)		intraQ = intra_tab;	else		intraQ = zigof(m.intra);	if (m.nintra == nil)		nintraQ = nintra_tab;	else		nintraQ = zigof(m.nintra);	rtmp = array[6] of array of int;	for (i = 0; i < 6; i++)		rtmp[i] = array[64] of int;	zeros1 = zeros[1:];} zarray(n: int, v: byte): array of byte{	return array[n] of { * => v };} frame(): ref YCbCr{	y := zarray(width * height, byte 0);	b := zarray(w2 * h2, byte 128);	r := zarray(w2 * h2, byte 128);	return ref YCbCr(y, b, r);} zigof(a: array of int): array of int{	z := array[64] of int;	for (i := 0; i < 64; i++)		z[zig[i]] = a[i];	return z;} invQ_intra(a: array of Pair, q: int, b: array of int){	(nil, t) := a[0];	b[0] = t * 8;	b[1:] = zeros1;	n := 1;	i := 1;	while (n < len a) {		(r, l) := a[n++];		i += r;		x := zig[i++];		if (l > 0) {			v := l * q * intraQ[x] >> 3;			if (v > 2047)				b[x] = 2047;			else				b[x] = (v - 1) | 1;		} else {			v := (l * q * intraQ[x] + 7) >> 3;			if (v < -2048)				b[x] = -2048;			else				b[x] = v | 1;		}		#sys->print("%d %d %d %d\n", x, r, l, b[x]);	}} invQ_nintra(a: array of Pair, q: int, b: array of int){	b[0:] = zeros;	i := 0;	for (n := 0; n < len a; n++) {		(r, l) := a[n];		i += r;		if (l == 0) {			raisex("zero level");			i++;			continue;		}		x := zig[i++];		if (l > 0) {			v := ((l << 1) + 1) * q * nintraQ[x] >> 4;			if (v > 2047)				b[x] = 2047;			else				b[x] = (v - 1) | 1;		} else {			v := (((l << 1) - 1) * q * nintraQ[x] + 15) >> 4;			if (v < -2048)				b[x] = -2048;			else				b[x] = v | 1;		}		#sys->print("%d %d %d %d\n", x, r, l, b[x]);	}} yzero(v: array of byte, base: int){	x := 0;	i := 8;	do {		n := base;		j := 8;		do			v[n++] = byte 0;		while (--j > 0);		base += width;	} while (--i > 0);} czero(v: array of byte, base: int){	x := 0;	i := 8;	do {		n := base;		j := 8;		do			v[n++] = byte 128;		while (--j > 0);		base += w2;	} while (--i > 0); } blockzero(d: ref YCbCr){	yzero(d.Y, ybase);	yzero(d.Y, ybase + 8);	yzero(d.Y, ybase + yskip);	yzero(d.Y, ybase + 8 + yskip);	czero(d.Cb, cbase);	czero(d.Cr, cbase);} ydistr(a: array of int, v: array of byte, base: int){	x := 0;	i := 8;	do {		n := base;		j := 8;		do			v[n++] = clamp[a[x++] + CLOFF];		while (--j > 0);		base += width;	} while (--i > 0);} cdistr(a: array of int, v: array of byte, base: int){	x := 0;	i := 8;	do {		n := base;		j := 8;		do			v[n++] = clamp[a[x++] + CLOFF];		while (--j > 0);		base += w2;	} while (--i > 0); } invQ_intra_block(b: array of array of Pair, q: int, pred: int, d: ref YCbCr){	a, dc: array of int;	if (pred)		dc = past;	else		dc = pinit;	p := dc[0];	for (i := 0; i < 4; i++) {		a = rtmp[i];		#sys->print("%d\n", i);		invQ_intra(b[i], q, a);		p += a[0];		a[0] = p;		#sys->print("%d\n", a[0]);		idct->idct(a);	}	past[0] = p;	for (i = 4; i < 6; i++) {		p = dc[i - 3];		a = rtmp[i];		#sys->print("%d\n", i);		invQ_intra(b[i], q, a);		p += a[0];		a[0] = p;		#sys->print("%d\n", a[0]);		past[i - 3] = p;		idct->idct(a);	}	ydistr(rtmp[0], d.Y, ybase);	ydistr(rtmp[1], d.Y, ybase + 8);	ydistr(rtmp[2], d.Y, ybase + yskip);	ydistr(rtmp[3], d.Y, ybase + 8 + yskip);	cdistr(rtmp[4], d.Cb, cbase);	cdistr(rtmp[5], d.Cr, cbase);} invQ_nintra_block(b: array of array of Pair, q: int){	for (i := 0; i < 6; i++) {		p := b[i];		if (p != nil) {			a := rtmp[i];			#sys->print("%d\n", i);			invQ_nintra(p, q, a);			idct->idct(a);			rflag[i] = 1;		} else			rflag[i] = 0;	}} mbr, ybase, cbase: int; nextmb(){	if (--mbr == 0) {		ybase += yadj;		cbase += cadj;		mbr = mps;	} else {		ybase += 16;		cbase += 8;	}} copyblock(s, d: array of byte, b, n, w: int){	i := 8;	do {		d[b:] = s[b:b+n];		b += w;	} while (--i > 0);} copyblockdisp(s, d: array of byte, b, n, w, p: int){	i := 8;	p += b;	do {		d[b:] = s[p:p+n];		b += w;		p += w;	} while (--i > 0);} interpblock(s0, s1, d: array of byte, b, n, w, p0, p1: int){	i := 8;	do {		dx := b;		s0x := b + p0;		s1x := b + p1;		j := n;		do			d[dx++] = byte ((int s0[s0x++] + int s1[s1x++] + 1) >> 1);		while (--j > 0);		b += w;	} while (--i > 0);} deltablock(s: array of byte, r: array of int, d: array of byte, b, w, o: int){	rx := 0;	i := 8;	do {		dx := b;		sx := b + o;		j := 8;		do			d[dx++] = clamp[CLOFF + int s[sx++] + r[rx++]];		while (--j > 0);		b += w;	} while (--i > 0);} deltainterpblock(s0, s1: array of byte, r: array of int, d: array of byte, b, w, o0, o1: int){	rx := 0;	i := 8;	do {		dx := b;		s0x := b + o0;		s1x := b + o1;		j := 8;		do			d[dx++] = clamp[CLOFF + ((int s0[s0x++] + int s1[s1x++] + 1) >> 1) + r[rx++]];		while (--j > 0);		b += w;	} while (--i > 0);} dispblock(s, d: array of byte, n, b, w, o: int){	if (rflag[n])		deltablock(s, rtmp[n], d, b, w, o);	else		copyblockdisp(s, d, b, 8, w, o);} genblock(s0, s1, d: array of byte, n, b, w, o0, o1: int){	if (rflag[n])		deltainterpblock(s0, s1, rtmp[n], d, b, w, o0, o1);	else		interpblock(s0, s1, d, b, 8, w, o0, o1);} copymb(){	copyblock(R.Y, P.Y, ybase, 16, width);	copyblock(R.Y, P.Y, ybase + yskip, 16, width);	copyblock(R.Cb, P.Cb, cbase, 8, w2);	copyblock(R.Cr, P.Cr, cbase, 8, w2);} deltamb(){	dispblock(R.Y, P.Y, 0, ybase, width, 0);	dispblock(R.Y, P.Y, 1, ybase + 8, width, 0);	dispblock(R.Y, P.Y, 2, ybase + yskip, width, 0);	dispblock(R.Y, P.Y, 3, ybase + 8 + yskip, width, 0);	dispblock(R.Cb, P.Cb, 4, cbase, w2, 0);	dispblock(R.Cr, P.Cr, 5, cbase, w2, 0);} copymbforw(){	copyblockdisp(N.Y, B.Y, ybase, 16, width, ydf);	copyblockdisp(N.Y, B.Y, ybase + yskip, 16, width, ydf);	copyblockdisp(N.Cb, B.Cb, cbase, 8, w2, cdf);	copyblockdisp(N.Cr, B.Cr, cbase, 8, w2, cdf);} copymbback(){	copyblockdisp(M.Y, B.Y, ybase, 16, width, ydb);	copyblockdisp(M.Y, B.Y, ybase + yskip, 16, width, ydb);	copyblockdisp(M.Cb, B.Cb, cbase, 8, w2, cdb);	copyblockdisp(M.Cr, B.Cr, cbase, 8, w2, cdb);} copymbbackforw(){	interpblock(M.Y, N.Y, B.Y, ybase, 16, width, ydb, ydf);	interpblock(M.Y, N.Y, B.Y, ybase + yskip, 16, width, ydb, ydf);	interpblock(M.Cb, N.Cb, B.Cb, cbase, 8, w2, cdb, cdf);	interpblock(M.Cr, N.Cr, B.Cr, cbase, 8, w2, cdb, cdf);} deltambforw(){	dispblock(N.Y, B.Y, 0, ybase, width, ydf);	dispblock(N.Y, B.Y, 1, ybase + 8, width, ydf);	dispblock(N.Y, B.Y, 2, ybase + yskip, width, ydf);	dispblock(N.Y, B.Y, 3, ybase + 8 + yskip, width, ydf);	dispblock(N.Cb, B.Cb, 4, cbase, w2, cdf);	dispblock(N.Cr, B.Cr, 5, cbase, w2, cdf);} deltambback(){	dispblock(M.Y, B.Y, 0, ybase, width, ydb);	dispblock(M.Y, B.Y, 1, ybase + 8, width, ydb);	dispblock(M.Y, B.Y, 2, ybase + yskip, width, ydb);	dispblock(M.Y, B.Y, 3, ybase + 8 + yskip, width, ydb);	dispblock(M.Cb, B.Cb, 4, cbase, w2, cdb);	dispblock(M.Cr, B.Cr, 5, cbase, w2, cdb);} deltambbackforw(){	genblock(M.Y, N.Y, B.Y, 0, ybase, width, ydb, ydf);	genblock(M.Y, N.Y, B.Y, 1, ybase + 8, width, ydb, ydf);	genblock(M.Y, N.Y, B.Y, 2, ybase + yskip, width, ydb, ydf);	genblock(M.Y, N.Y, B.Y, 3, ybase + 8 + yskip, width, ydb, ydf);	genblock(M.Cb, N.Cb, B.Cb, 4, cbase, w2, cdb, cdf);	genblock(M.Cr, N.Cr, B.Cr, 5, cbase, w2, cdb, cdf);} deltambinterp(){	case vflags & (Mpegio->MB_MF | Mpegio->MB_MB) {	Mpegio->MB_MF =>		deltambforw();	Mpegio->MB_MB =>		deltambback();	Mpegio->MB_MF | Mpegio->MB_MB =>		deltambbackforw();	* =>		raisex("bad vflags");	}} interpmb(){	case vflags & (Mpegio->MB_MF | Mpegio->MB_MB) {	Mpegio->MB_MF =>		copymbforw();	Mpegio->MB_MB =>		copymbback();	Mpegio->MB_MF | Mpegio->MB_MB =>		copymbbackforw();	* =>		raisex("bad vflags");	}} Idecode(p: ref Picture): ref YCbCr{	sa := p.slices;	n := 0;

Lines 1–500 of 831.