[Sumover-dev] [svn commit] r3805 - in vic/trunk: codec tcl

sumover-dev at cs.ucl.ac.uk sumover-dev at cs.ucl.ac.uk
Wed Sep 6 02:36:00 BST 2006


Author: rhys
Date: Wed Sep  6 02:34:26 2006
New Revision: 3805

Added:
   vic/trunk/tcl/ui-ctrlmenu.tcl.h261as
Modified:
   vic/trunk/codec/encoder-h261as.cpp
   vic/trunk/rtp/rtp.h
   vic/trunk/rtp/session.cpp
   vic/trunk/tcl/cf-main.tcl

Log:
Added DV payload types to rtp code.
Implemented H261AS encoder, VIC can send h261as to VP.



Modified: vic/trunk/codec/encoder-h261as.cpp
==============================================================================
--- vic/trunk/codec/encoder-h261as.cpp	(original)
+++ vic/trunk/codec/encoder-h261as.cpp	Wed Sep  6 02:34:26 2006
@@ -1,38 +1,3 @@
-/*
- * Copyright (c) 1994-1995 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by the University of
- *      California, Berkeley and the Network Research Group at
- *      Lawrence Berkeley Laboratory.
- * 4. Neither the name of the University nor of the Laboratory may be used
- *    to endorse or promote products derived from this software without
- *    specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-static const char rcsid[] =
-    "@(#) $Header$ (LBL)";
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -51,6 +16,7 @@
 #include "module.h"
 
 #define HDRSIZE (sizeof(rtphdr) + 4)
+#define DEFAULT_THRESHOLD 48
 #define	CIF_WIDTH	352
 #define	CIF_HEIGHT	288
 #define	QCIF_WIDTH	176
@@ -116,177 +82,151 @@
 
 class H261ASEncoder : public TransmitterModule {
     public:
+	H261ASEncoder();
+	~H261ASEncoder();
 	void setq(int q);
+	int consume(const VideoFrame*);
     protected:
-	H261ASEncoder(int ft);
-	~H261ASEncoder();
 	int encode(const VideoFrame*, const u_int8_t *crvec);
 	int command(int argc, const char*const* argv);
 	void encode_blk(const short* blk, const char* lm);
 	int flush(pktbuf* pb, int nbit, pktbuf* npb);
 	char* make_level_map(int q, u_int fthresh);
 	void setquantizers(int lq, int mq, int hq);
-
-	virtual void size(int w, int h) = 0;
-	virtual void encode_mb(u_int mba, const u_char* frm,
-		       u_int loff, u_int coff, int how) = 0;
-
-	/* bit buffer */
-	BB_INT bb_;
-	u_int nbb_;
-
-	u_char* bs_;
-	u_char* bc_;
-	int sbit_;
-
-	u_char lq_;		/* low quality quantizer */
-	u_char mq_;		/* medium quality quantizer */
-	u_char hq_;		/* high quality quantizer */
-	u_char mquant_;		/* the last quantizer we sent to other side */
-	int quant_required_;	/* 1 if not quant'd in dct */
-	u_int ngob_;
-	u_int mba_;
-
-	u_int cif_;		/* 1 for CIF, 0 for QCIF */
-	u_int bstride_;
-	u_int lstride_;
-	u_int cstride_;
-
-	u_int loffsize_;	/* amount of 1 luma block */
-	u_int coffsize_;	/* amount of 1 chroma block */
-	u_int bloffsize_;	/* amount of 1 block advance */
-
-	const char* llm_[32];	/* luma dct val -> level maps */
-	const char* clm_[32];	/* chroma dct val -> level maps */
-
-	float lqt_[64];		/* low quality quantizer */
-	float mqt_[64];		/* medium quality quantizer */
-	float hqt_[64];		/* high quality quantizer */
-
-	u_int coff_[12];	/* where to find U given gob# */
-	u_int loff_[12];	/* where to find Y given gob# */
-	u_int blkno_[12];	/* for CR */
-};
-
-class H261ASDCTEncoder : public H261ASEncoder {
-    public:
-	H261ASDCTEncoder();
-	int consume(const VideoFrame*);
 	void size(int w, int h);
-    protected:
 	void encode_mb(u_int mba, const u_char* frm,
 		       u_int loff, u_int coff, int how);
-};
 
-class H261ASPixelEncoder : public H261ASEncoder {
-    public:
-	H261ASPixelEncoder();
-	int consume(const VideoFrame*);
-	void size(int w, int h);
-    protected:
-	void encode_mb(u_int mba, const u_char* frm,
-		       u_int loff, u_int coff, int how);
+        u_int width;
+        u_int height;
+        u_char *frame_buffer;
+        u_int frame_buffer_size;
+
+        u_char *crref;
+        u_char *crvec;
+
+        int nblk;
+        int blkw;
+        int blkh;
+        int rover;
+        int threshold;
+        int scan;
+
+        u_char *bs;
+        u_char *bc;
+        int bb;
+        int nbb;
+        int sbit;
+        int tx;
+        int lq;
+        int mq;
+        int hq;
+        u_int ngob;
+        u_int nblocks;
+        int mquant;
+        int mba;
+
+        int *loff_table;
+        int *coff_table;
+        int *blkno_table;
+
+        float lqt[64];
+        float mqt[64];
+        float hqt[64];
+
+        const char *llm[32];
+        const char *clm[32];
 };
 
 static class H261ASEncoderMatcher : public Matcher {
     public:
 	H261ASEncoderMatcher() : Matcher("module") {}
 	TclObject* match(const char* fmt) {
-		if (strcasecmp(fmt, "h261as/pixel") == 0)
-			return (new H261ASPixelEncoder);
-		if (strcasecmp(fmt, "h261as/dct") == 0)
-			return (new H261ASDCTEncoder);
-		/* XXX for now, this is compatible with ui-ctrlmenu.tcl */
-		if (strcasecmp(fmt, "h261as") == 0)
-			return (new H261ASPixelEncoder);
+		if (strcasecmp(fmt, "h261as") == 0 ||
+		    strcasecmp(fmt, "h.261as") == 0)
+			return (new H261ASEncoder);
 		return (0);
 	}
 } encoder_matcher_h261as;
 
 
-H261ASEncoder::H261ASEncoder(int ft) : TransmitterModule(ft),
-	bs_(0), bc_(0), ngob_(12)
+H261ASEncoder::H261ASEncoder() : TransmitterModule(FT_YUV_411),
+				 frame_buffer(0),
+				 frame_buffer_size(0),
+				 crref(0),
+				 crvec(0),
+				 nblk(0),
+				 blkw(0),
+				 blkh(0),
+				 rover(0),
+				 threshold(DEFAULT_THRESHOLD),
+				 scan(0),
+				 loff_table(0),
+				 coff_table(0)
 {
 	for (int q = 0; q < 32; ++q) {
-		llm_[q] = 0;
-		clm_[q] = 0;
+		llm[q] = 0;
+		clm[q] = 0;
 	}
+	setq(10);
 }
 
 H261ASEncoder::~H261ASEncoder()
 {
 	for (int q = 0; q < 32; ++q) {
-		if (llm_[q] != 0)
-			delete llm_[q]; //SV-XXX: Debian
-		if (clm_[q] != 0)
-			delete clm_[q]; //SV-XXX: Debian
+		if (llm[q] != 0)
+			delete llm[q]; //SV-XXX: Debian
+		if (clm[q] != 0)
+			delete clm[q]; //SV-XXX: Debian
 	}
 }
 
-H261ASPixelEncoder::H261ASPixelEncoder() : H261ASEncoder(FT_YUV_CIF)
-{
-	quant_required_ = 0;
-	setq(10);
-}
-
-H261ASDCTEncoder::H261ASDCTEncoder() : H261ASEncoder(FT_DCT)
-{
-	quant_required_ = 1;
-	setq(10);
-}
-
 /*
  * Set up the forward DCT quantization table for
  * INTRA mode operation.
  */
 void
-H261ASEncoder::setquantizers(int lq, int mq, int hq)
+H261ASEncoder::setquantizers(int _lq, int _mq, int _hq)
 {
 	int qt[64];
+        lq = _lq;
 	if (lq > 31)
 		lq = 31;
 	if (lq <= 0)
 		lq = 1;
-	lq_ = lq;
 
+        mq = _mq;
 	if (mq > 31)
 		mq = 31;
 	if (mq <= 0)
 		mq = 1;
-	mq_ = mq;
 
+        hq = _hq;
 	if (hq > 31)
 		hq = 31;
 	if (hq <= 0)
 		hq = 1;
-	hq_ = hq;
 
-	/*
-	 * quant_required_ indicates quantization is not folded
-	 * into fdct [because fdct is not performed]
-	 */
-	if (quant_required_ == 0) {
-		/*
-		 * Set the DC quantizer to 1, since we want to do this
-		 * coefficient differently (i.e., the DC is rounded while
-		 * the AC terms are truncated).
-		 */
-		qt[0] = 1;
-		int i;
-		for (i = 1; i < 64; ++i)
-			qt[i] = lq_ << 1;
-		fdct_fold_q(qt, lqt_);
-
-		qt[0] = 1;
-		for (i = 1; i < 64; ++i)
-			qt[i] = mq_ << 1;
-		fdct_fold_q(qt, mqt_);
-
-		qt[0] = 1;
-		for (i = 1; i < 64; ++i)
-			qt[i] = hq_ << 1;
-		fdct_fold_q(qt, hqt_);
-	}
+        /*
+         * Set the DC quantizer to 1, since we want to do this
+         * coefficient differently (i.e., the DC is rounded while
+         * the AC terms are truncated).
+         */
+        qt[0] = 1;
+        int i;
+        for (i = 1; i < 64; ++i)
+          qt[i] = lq << 1;
+        fdct_fold_q(qt, lqt);
+        
+        qt[0] = 1;
+        for (i = 1; i < 64; ++i)
+          qt[i] = mq << 1;
+        fdct_fold_q(qt, mqt);
+        
+        qt[0] = 1;
+        for (i = 1; i < 64; ++i)
+          qt[i] = hq << 1;
+        fdct_fold_q(qt, hqt);
 }
 
 void
@@ -296,109 +236,75 @@
 }
 
 void
-H261ASPixelEncoder::size(int w, int h)
+H261ASEncoder::size(int w, int h)
 {
-	Module::size(w, h);
-	if (w == CIF_WIDTH && h == CIF_HEIGHT) {
-		/* CIF */
-		cif_ = 1;
-		ngob_ = 12;
-		bstride_ = 11;
-		lstride_ = 16 * CIF_WIDTH - CIF_WIDTH / 2;
-		cstride_ = 8 * 176 - 176 / 2;
-		loffsize_ = 16;
-		coffsize_ = 8;
-		bloffsize_ = 1;
-	} else if (w == QCIF_WIDTH && h == QCIF_HEIGHT) {
-		/* QCIF */
-		cif_ = 0;
-		ngob_ = 6; /* not really number of GOBs, just loop limit */
-		bstride_ = 0;
-		lstride_ = 16 * QCIF_WIDTH - QCIF_WIDTH;
-		cstride_ = 8 * 88 - 88;
-		loffsize_ = 16;
-		coffsize_ = 8;
-		bloffsize_ = 1;
-	} else {
-		/*XXX*/
-		fprintf(stderr, "H261ASPixelEncoder: H.261 bad geometry: %dx%d\n",
-			w, h);
-		exit(1);
-	}
-	u_int loff = 0;
-	u_int coff = 0;
-	u_int blkno = 0;
-	for (u_int gob = 0; gob < ngob_; gob += 2) {
-		loff_[gob] = loff;
-		coff_[gob] = coff;
-		blkno_[gob] = blkno;
-		/* width of a GOB (these aren't ref'd in QCIF case) */
-		loff_[gob + 1] = loff + 11 * 16;
-		coff_[gob + 1] = coff + 11 * 8;
-		blkno_[gob + 1] = blkno + 11;
-
-		/* advance to next GOB row */
-		loff += (16 * 16 * MBPERGOB) << cif_;
-		coff += (8 * 8 * MBPERGOB) << cif_;
-		blkno += MBPERGOB << cif_;
-	}
+        Module::size(w, h);
+  
+        if (w % 16 != 0) {
+                w += 16 - (w % 16);
+        }
+        if (h % 16 != 0) {
+                h += 16 - (h % 16);
+        }
+
+        width = w;
+        height = h;
+
+        if (frame_buffer) {
+                delete [] frame_buffer;
+        }
+        frame_buffer_size = (width * height * 3)/2;
+        frame_buffer = new u_char[frame_buffer_size];
+        memset(frame_buffer, 127, frame_buffer_size);
+
+        if (crref) {
+                delete [] crref;
+        }
+        crref = new u_char[width * height];
+        
+        if (crvec) {
+                delete [] crvec;
+        }
+        nblk = (width * height) >> 8;
+        crvec = new u_char[nblk];
+
+        blkw = width/16;
+        blkh = height/16;
+
+        nblocks = blkw * blkh;
+        ngob = nblocks/33;
+        if (ngob * 33 < nblocks) {
+                ngob ++;
+        }
+
+        if (loff_table) {
+                delete [] loff_table;
+        }
+        loff_table = new int[nblocks];
+        if (coff_table) {
+                delete [] coff_table;
+        }
+        coff_table = new int[nblocks];
+
+        int i = 0;
+        int loff = 0;
+        int coff = 0;
+        int l_rs = 15 * width;
+        int c_rs = 7 * width/2;
+        for (int y = 0; y < blkh; y ++) {
+                for (int x = 0; x < blkw; x ++, i ++) {
+                        loff_table[i] = loff;
+                        coff_table[i] = coff;
+
+                        loff += 16;
+                        coff += 8;
+                }
+
+                loff += l_rs;
+                coff += c_rs;
+        }
 }
 
-void
-H261ASDCTEncoder::size(int w, int h)
-{
-
-	Module::size(w, h);
-	if (w == CIF_WIDTH && h == CIF_HEIGHT) {
-		/* CIF */
-		cif_ = 1;
-		ngob_ = 12;
-		bstride_ = 11;
-		lstride_ = - (11 * (64*BMB)) + 2 * 11 * 64 * BMB;
-		cstride_ = - (11 * (64*BMB)) + 2 * 11 * 64 * BMB;
-		loffsize_ = 64 * BMB;
-		coffsize_ = 64 * BMB;
-		bloffsize_ = 1;
-	} else if (w == QCIF_WIDTH && h == QCIF_HEIGHT) {
-		/* QCIF */
-		cif_ = 0;
-		ngob_ = 6; /* not really number of GOBs, just loop limit */
-		bstride_ = 0;
-		lstride_ = 0;
-		cstride_ = 0;
-		loffsize_ = 64 * BMB;
-		coffsize_ = 64 * BMB;
-		bloffsize_ = 1;
-	} else {
-		/*XXX*/
-		fprintf(stderr, "H261ASDCTEncoder: H.261 bad geometry: %dx%d\n",
-			w, h);
-		exit(1);
-	}
-
-	u_int gob;
-	for (gob = 0; gob < ngob_; gob += 2) {
-
-		if (gob != 0) {
-			loff_[gob] = loff_[gob-2] +
-				(MBPERGOB << cif_) * BMB * 64;
-			coff_[gob] = coff_[gob-2] +
-				(MBPERGOB << cif_) * BMB * 64;
-			blkno_[gob] = blkno_[gob-2] +
-				(MBPERGOB << cif_);
-		} else {
-			loff_[0] = 0;
-			coff_[0] = loff_[0] + 4 * 64;	// 4 Y's
-			blkno_[0] = 0;
-		}
-
-		loff_[gob + 1] = loff_[gob] + 11 * BMB * 64;
-		coff_[gob + 1] = coff_[gob] + 11 * BMB * 64;
-		blkno_[gob + 1] = blkno_[gob] + 11;
-	}
-}
-
-
 int
 H261ASEncoder::command(int argc, const char*const* argv)
 {
@@ -427,7 +333,7 @@
 	int i;
 	lm[0] = 0;
 	flm[0] = 0;
-	q = quant_required_? q << 1 : 0;
+	q = 0;
 	for (i = 1; i < 0x800; ++i) {
 		int l = i;
 		if (q)
@@ -450,9 +356,9 @@
 void
 H261ASEncoder::encode_blk(const short* blk, const char* lm)
 {
-	BB_INT bb = bb_;
-	u_int nbb = nbb_;
-	u_char* bc = bc_;
+	BB_INT t_bb = bb;
+	u_int t_nbb = nbb;
+	u_char* t_bc = bc;
 
 	/*
 	 * Quantize DC.  Round instead of truncate.
@@ -468,7 +374,7 @@
 		/* per Table 6/H.261 */
 		dc = 255;
 	/* Code DC */
-	PUT_BITS(dc, 8, nbb, bb, bc);
+	PUT_BITS(dc, 8, t_nbb, t_bb, t_bc);
 	int run = 0;
 	const u_char* colzag = &COLZAG[0];
 	for (int zag; (zag = *++colzag) != 0; ) {
@@ -487,39 +393,39 @@
 				val = (1 << 14) | (run << 8) | (level & 0xff);
 				nb = 20;
 			}
-			PUT_BITS(val, nb, nbb, bb, bc);
+			PUT_BITS(val, nb, t_nbb, t_bb, t_bc);
 			run = 0;
 		} else
 			++run;
 	}
 	/* EOB */
-	PUT_BITS(2, 2, nbb, bb, bc);
+	PUT_BITS(2, 2, t_nbb, t_bb, t_bc);
 
-	bb_ = bb;
-	nbb_ = nbb;
-	bc_ = bc;
+	bb = t_bb;
+	nbb = t_nbb;
+	bc = t_bc;
 }
 
 /*
- * H261ASPixelEncoder::encode_mb
+ * H261ASEncoder::encode_mb
  *	encode a macroblock given a set of input YUV pixels
  */
 void
-H261ASPixelEncoder::encode_mb(u_int mba, const u_char* frm,
+H261ASEncoder::encode_mb(u_int mbal, const u_char* frm,
 			    u_int loff, u_int coff, int how)
 {
 	register int q;
 	float* qt;
 	if (how == CR_MOTION) {
-		q = lq_;
-		qt = lqt_;
+		q = lq;
+		qt = lqt;
 	} else if (how == CR_BG) {
-		q = hq_;
-		qt = hqt_; 
+		q = hq;
+		qt = hqt; 
 	} else {
 		/* must be at age threshold */
-		q = mq_;
-		qt = mqt_; 
+		q = mq;
+		qt = mqt; 
 	}
 
 	/*
@@ -529,7 +435,7 @@
 	 */
 	/*XXX this can be u_char instead of short but need smarts in fdct */
 	short blk[64 * 6];
-	register int stride = width_;
+	register int stride = width;
 	/* luminance */
 	const u_char* p = &frm[loff];
 	fdct(p, stride, blk + 0, qt);
@@ -537,7 +443,7 @@
 	fdct(p + 8 * stride, stride, blk + 128, qt);
 	fdct(p + (8 * stride + 8), stride, blk + 192, qt);
 	/* chominance */
-	int fs = framesize_;
+	int fs = stride * height;
 	p = &frm[fs + coff];
 	stride >>= 1;
 	fdct(p, stride, blk + 256, qt);
@@ -580,138 +486,43 @@
 		}
 	}
 
-	u_int m = mba - mba_;
-	mba_ = mba;
+	u_int m = mbal - mba;
+	mba = mbal;
 	huffent* he = &hte_mba[m - 1];
 	/* MBA */
-	PUT_BITS(he->val, he->nb, nbb_, bb_, bc_);
-	if (q != mquant_) {
+	PUT_BITS(he->val, he->nb, nbb, bb, bc);
+	if (q != mquant) {
 		/* MTYPE = INTRA + TC + MQUANT */
-		PUT_BITS(1, 7, nbb_, bb_, bc_);
-		PUT_BITS(q, 5, nbb_, bb_, bc_);
-		mquant_ = q;
+		PUT_BITS(1, 7, nbb, bb, bc);
+		PUT_BITS(q, 5, nbb, bb, bc);
+		mquant = q;
 	} else {
 		/* MTYPE = INTRA + TC (no quantizer) */
-		PUT_BITS(1, 4, nbb_, bb_, bc_);
+		PUT_BITS(1, 4, nbb, bb, bc);
 	}
 
 	/* luminance */
-	const char* lm = llm_[q];
+	const char* lm = llm[q];
 	if (lm == 0) {
 		lm = make_level_map(q, 1);
-		llm_[q] = lm;
-		clm_[q] = make_level_map(q, 2);
+		llm[q] = lm;
+		clm[q] = make_level_map(q, 2);
 	}
 	encode_blk(blk + 0, lm);
 	encode_blk(blk + 64, lm);
 	encode_blk(blk + 128, lm);
 	encode_blk(blk + 192, lm);
 	/* chominance */
-	lm = clm_[q];
+	lm = clm[q];
 	encode_blk(blk + 256, lm);
 	encode_blk(blk + 320, lm);
 }
 
-
-/*
- * H261ASDCTEncoder::encode_mb
- *	encode a macroblock given a set of input DCT coefs
- *	each coef is stored as a short
- */
-void
-H261ASDCTEncoder::encode_mb(u_int mba, const u_char* frm,
-			  u_int loff, u_int coff, int how)
-{
-	short *lblk = (short *)frm + loff;
-	short *ublk = (short *)frm + coff;
-	short *vblk = (short *)frm + coff + 64;
-
-	register u_int q;
-	if (how == CR_MOTION)
-		q = lq_;
-	else if (how == CR_BG)
-		q = hq_;
-	else
-		/* must be at age threshold */
-		q = mq_;
-
-	/*
-	 * if the default quantizer is too small to handle the coef.
-	 * dynamic range, spin through the blocks and see if any
-	 * coef. would significantly overflow.
-	 */
-	if (q < 8) {
-		register int cmin = 0, cmax = 0;
-		register short* bp = lblk;
-		register int i, j;
-
-		// Y U and V blocks
-		for (i = 6; --i >= 0; ) {
-			++bp;	// ignore dc coef
-			for (j = 63; --j >= 0; ) {
-				register int v = *bp++;
-				if (v < cmin)
-					cmin = v;
-				else if (v > cmax)
-					cmax = v;
-			}
-		}
-
-		if (cmax < -cmin)
-			cmax = -cmin;
-		cmax /= (q << 1);
-		if (cmax >= 128) {
-			/* need to re-quantize */
-			register int s;
-
-			for (s = 1; cmax >= (128 << s); ++s) {
-			}
-			q <<= s;
-
-		}
-	}
-
-	u_int m = mba - mba_;
-	mba_ = mba;
-	huffent* he = &hte_mba[m - 1];
-	/* MBA */
-	PUT_BITS(he->val, he->nb, nbb_, bb_, bc_);
-	if (q != mquant_) {
-		/* MTYPE = INTRA + TC + MQUANT */
-		PUT_BITS(1, 7, nbb_, bb_, bc_);
-		PUT_BITS(q, 5, nbb_, bb_, bc_);
-		mquant_ = q;
-	} else {
-		/* MTYPE = INTRA + TC (no quantizer) */
-		PUT_BITS(1, 4, nbb_, bb_, bc_);
-	}
-
-	/* luminance */
-	const char* lm = llm_[q];
-	if (lm == 0) {
-		/*
-		 * the filter thresh is 0 since we assume the jpeg percept.
-		 * quantizer already did the filtering.
-		 */
-		lm = make_level_map(q, 0);
-		llm_[q] = lm;
-		clm_[q] = make_level_map(q, 0);
-	}
-	encode_blk(lblk + 0, lm);
-	encode_blk(lblk + 64, lm);
-	encode_blk(lblk + 128, lm);
-	encode_blk(lblk + 192, lm);
-	/* chominance */
-	lm = clm_[q];
-	encode_blk(ublk, lm);
-	encode_blk(vblk, lm);
-}
-
 int
 H261ASEncoder::flush(pktbuf* pb, int nbit, pktbuf* npb)
 {
 	/* flush bit buffer */
-	STORE_BITS(bb_, bc_);
+	STORE_BITS(bb, bc);
 
 	int cc = (nbit + 7) >> 3;
 	int ebit = (cc << 3) - nbit;
@@ -725,49 +536,22 @@
 	if (npb == 0)
 		rh->rh_flags |= htons(RTP_M);
 
-	int h = *(u_int*)(rh + 1) | ebit << 26 | sbit_ << 29;
+	int h = *(u_int*)(rh + 1) | ebit << 26;
 	*(u_int*)(rh + 1) = htonl(h);
 
 	if (npb != 0) {
-		u_char* nbs = &npb->data[HDRSIZE];
-		u_int bc = (bc_ - bs_) << 3;
-		int tbit = bc + nbb_;
-		int extra = ((tbit + 7) >> 3) - (nbit >> 3);
-		if (extra > 0)
-			memcpy(nbs, bs_ + (nbit >> 3), extra);
-		bs_ = nbs;
-		sbit_ = nbit & 7;
-		tbit -= nbit &~ 7;
-		bc = tbit &~ (NBIT - 1);
-		nbb_ = tbit - bc;
-		bc_ = bs_ + (bc >> 3);
-		/*
-		 * Prime the bit buffer.  Be careful to set bits that
-		 * are not yet in use to 0, since output bits are later
-		 * or'd into the buffer.
-		 */
-		if (nbb_ > 0) {
-			u_int n = NBIT - nbb_;
-			bb_ = (LOAD_BITS(bc_) >> n) << n;
-		} else
-			bb_ = 0;
+		bs = &npb->data[HDRSIZE];
+		bc = bs;
+		bb = 0;
+		nbb = 0;
+		sbit = 0;
 	}
 	tx_->send(pb);
 
 	return (cc + HDRSIZE);
 }
 
-int H261ASDCTEncoder::consume(const VideoFrame *vf)
-{
-	if (!samesize(vf))
-		size(vf->width_, vf->height_);
-
-	DCTFrame* df = (DCTFrame *)vf;
-
-	return(encode(df, df->crvec_));
-}
-
-int H261ASPixelEncoder::consume(const VideoFrame *vf)
+int H261ASEncoder::consume(const VideoFrame *vf)
 {
 	if (!samesize(vf))
 		size(vf->width_, vf->height_);
@@ -782,48 +566,37 @@
 {
 	tx_->flush();
 
-	pktbuf* pb = pool_->alloc(vf->ts_, RTP_PT_H261);
-	bs_ = &pb->data[HDRSIZE];
-	bc_ = bs_;
+	pktbuf* pb = pool_->alloc(vf->ts_, RTP_PT_H261AS);
+	bs = &pb->data[HDRSIZE];
+	bc = bs;
 	u_int ec = (tx_->mtu() - HDRSIZE) << 3;
-	bb_ = 0;
-	nbb_ = 0;
-	sbit_ = 0;
+	bb = 0;
+	nbb = 0;
+
 	/* RTP/H.261 header */
 	rtphdr* rh = (rtphdr*)pb->data;
-	*(u_int*)(rh + 1) = 1 << 25 | lq_ << 10;
-
-	/* PSC */
-	PUT_BITS(0x0001, 16, nbb_, bb_, bc_);
-	/* GOB 0 -> picture header */
-	PUT_BITS(0, 4, nbb_, bb_, bc_);
-	/* TR (XXX should do this right) */
-	PUT_BITS(0, 5, nbb_, bb_, bc_);
-	/* PTYPE = CIF */
-	int pt = cif_ ? 4 : 0;
-	PUT_BITS(pt, 6, nbb_, bb_, bc_);
-	/* PEI */
-	PUT_BITS(0, 1, nbb_, bb_, bc_);
+	*(u_int*)(rh + 1) = lq << 24 | ((width >> 4) - 1) << 12 | ((height >> 4) - 1);
 
-	int step = cif_ ? 1 : 2;
 	int cc = 0;
-
 	u_int8_t* frm = vf->bp_;
-	for (u_int gob = 0; gob < ngob_; gob += step) {
-		u_int loff = loff_[gob];
-		u_int coff = coff_[gob];
-		u_int blkno = blkno_[gob];
-		u_int nbit = ((bc_ - bs_) << 3) + nbb_;
+	u_int nbit;
+	u_int blkno;
+
+	for (u_int gob = 0; gob < ngob; gob ++) {
+
+		blkno = 33 * gob;
 
 		/* GSC/GN */
-		PUT_BITS(0x10 | (gob + 1), 20, nbb_, bb_, bc_);
-		/* GQUANT/GEI */
-		mquant_ = lq_;
-		PUT_BITS(mquant_ << 1, 6, nbb_, bb_, bc_);
-
-		mba_ = 0;
-		int line = 11;
-		for (u_int mba = 1; mba <= 33; ++mba) {
+		PUT_BITS(0x0001, 16, nbb, bb, bc);
+		PUT_BITS(gob, 20, nbb, bb, bc);
+
+		/* GQUANT */
+		mquant = lq;
+		PUT_BITS(mquant, 5, nbb, bb, bc);
+		mba = 0;
+
+
+		for (u_int mbal = 1; mbal <= 33 && blkno < nblocks; ++mbal, blkno++) {
 			/*
 			 * If the conditional replenishment algorithm
 			 * has decided to send any of the blocks of
@@ -832,46 +605,50 @@
 			u_int s = crvec[blkno];
 
 			if ((s & CR_SEND) != 0) {
-				u_int mbpred = mba_;
-				encode_mb(mba, frm, loff, coff, CR_STATE(s));
-				u_int cbits = ((bc_ - bs_) << 3) + nbb_;
+
+				nbit = ((bc - bs) << 3) + nbb;
+				encode_mb(mbal, 
+					  frm, 
+					  loff_table[blkno], 
+					  coff_table[blkno], 
+					  CR_STATE(crvec[blkno]));
+				uint32_t cbits = ((bc - bs) << 3) + nbb;
 				if (cbits > ec) {
-					pktbuf* npb;
-					npb = pool_->alloc(vf->ts_, RTP_PT_H261);
-					cc += flush(pb, nbit, npb);
-					cbits -= nbit;
+					pktbuf *npb;
+					npb = pool_->alloc(vf->ts_, 
+							   RTP_PT_H261AS);
+					cc += flush(pb, 
+						    nbit, 
+						    npb);
 					pb = npb;
-					/* RTP/H.261 header */
-					u_int m = mbpred;
-					u_int g;
-					if (m != 0) {
-						g = gob + 1;
-						m -= 1;
-					} else
-						g = 0;
-
-					rh = (rtphdr*)pb->data;
-					*(u_int*)(rh + 1) =
-						1 << 25 |
-						m << 15 |
-						g << 20 |
-						mquant_ << 10;
-				}
-				nbit = cbits;
-			}
+	  
+					bs = &pb->data[HDRSIZE];
+					bc = bs;
+					bb = 0;
+					nbb = 0;
+					sbit = 0;
+
+					rtphdr* rh = (rtphdr*)pb->data;
+					*(u_int*)(rh + 1) = lq << 24 | ((width >> 4) - 1) << 12 | ((height >> 4) - 1);
+
 
-			loff += loffsize_;
-			coff += coffsize_;
-			blkno += bloffsize_;
-			if (--line <= 0) {
-				line = 11;
-				blkno += bstride_;
-				loff += lstride_;
-				coff += cstride_;
-			}
 
+					PUT_BITS(0x0001, 16, nbb, bb, bc);
+					PUT_BITS(gob, 20, nbb, bb, bc);
+					PUT_BITS(mquant, 5, nbb, bb, bc);
+
+					mba = 0;
+					encode_mb(mbal, 
+						  frm, 
+						  loff_table[blkno], 
+						  coff_table[blkno], 
+						  CR_STATE(crvec[blkno]));
+				} 
+			}
 		}
 	}
-	cc += flush(pb, ((bc_ - bs_) << 3) + nbb_, 0);
+
+	cc += flush(pb, ((bc - bs) << 3) + nbb, 0);
+
 	return (cc);
 }

Modified: vic/trunk/rtp/rtp.h
==============================================================================
--- vic/trunk/rtp/rtp.h	(original)
+++ vic/trunk/rtp/rtp.h	Wed Sep  6 02:34:26 2006
@@ -59,6 +59,7 @@
 #define RTP_PT_MP2T		33 	/* MPEG-II either audio or video */
 #define RTP_PT_H263P	42	/* ITU H.263 */
 #define RTP_PT_H263		34 	/* ITU H.263 */
+#define RTP_PT_DV               123     /* DV */
 
 /* backward compat hack for decoding RTPv1 ivs streams */
 #define RTP_PT_H261_COMPAT 127

Modified: vic/trunk/rtp/session.cpp
==============================================================================
--- vic/trunk/rtp/session.cpp	(original)
+++ vic/trunk/rtp/session.cpp	Wed Sep  6 02:34:26 2006
@@ -81,6 +81,7 @@
 		case RTP_PT_H263P:
 		case RTP_PT_LDCT:
 		case RTP_PT_PVH:
+	        case RTP_PT_DV:
 #ifdef USE_H261AS
 		case RTP_PT_H261AS:
 #endif 

Modified: vic/trunk/tcl/cf-main.tcl
==============================================================================
--- vic/trunk/tcl/cf-main.tcl	(original)
+++ vic/trunk/tcl/cf-main.tcl	Wed Sep  6 02:34:26 2006
@@ -47,6 +47,7 @@
 set rtp_type(34) h263
 set rtp_type(127) h261v1
 set rtp_type(77) h261as
+set rtp_type(123) dv
 
 proc vic_main {} {
 	global V tcl_platform

Added: vic/trunk/tcl/ui-ctrlmenu.tcl.h261as
==============================================================================
--- (empty file)
+++ vic/trunk/tcl/ui-ctrlmenu.tcl.h261as	Wed Sep  6 02:34:26 2006
@@ -0,0 +1,1526 @@
+#
+# Copyright (c) 1993-1995 Regents of the University of California.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#	This product includes software developed by the Computer Systems
+#	Engineering Group at Lawrence Berkeley Laboratory.
+# 4. Neither the name of the University nor of the Laboratory may be used
+#    to endorse or promote products derived from this software without
+#    specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+proc fork_histtolut { } {
+	global V
+	if { $V(dither) == "gray" } {
+		open_dialog "cannot optimize grayscale rendering"
+		return
+	}
+	#
+	# create a histogram object and collect stats from decoders
+	#
+	set ch [$V(colorModel) create-hist]
+	set active 0
+	foreach src [session active] {
+		set d [$src handler]
+		if { ![$src mute] && $d != "" } {
+			$d histogram $ch
+			set active 1
+		}
+	}
+	if !$active {
+		open_dialog "no active, unmuted sources"
+		delete $ch
+		return
+	}
+	set pid [pid]
+	set outfile /tmp/vicLUT.$pid
+	set infile /tmp/vicHIST.$pid
+
+	if { [$ch dump $infile] < 0 } {
+		open_dialog "couldn't create $infile"
+		delete $ch
+		return
+	}
+	delete $ch
+	#
+	# fork off a histtolut and use tk fileevent to call back
+	# finish_histtolut when the child is done
+	#
+	#XXX -n
+	set eflag ""
+	if { $V(dither) == "ed" } {
+		set eflag "-e"
+	}
+	if [catch \
+	  "open \"|histtolut $eflag -n 170 -o $outfile $infile\"" pipe] {
+		open_dialog "histtolut not installed in your path"
+		return
+	}
+	fileevent $pipe readable "finish_histtolut $pipe $infile $outfile"
+	# disable button while histtolut is running
+	$V(optionsMenu) entryconfigure "Optimize Colormap" \
+		-state disabled
+	.menu configure -cursor watch
+}
+
+proc finish_histtolut { pipe infile outfile } {
+	.menu configure -cursor ""
+	global V
+	$V(optionsMenu) entryconfigure "Optimize Colormap" \
+		-state normal
+	set cm $V(colorModel)
+	$cm free-colors
+	$cm lut $outfile
+	if ![$cm alloc-colors] {
+		#XXX unset lut
+		revert_to_gray
+	}
+	#XXX make this a proc
+	foreach src [session active] {
+		set d [$src handler]
+		if { $d != "" } {
+			$d redraw
+		}
+	}
+	fileevent $pipe readable ""
+	close $pipe
+}
+
+proc have_transmit_permission {} {
+	global inputDeviceList
+	return [expr [info exists inputDeviceList] && ![yesno recvOnly]]
+}
+
+#
+# Build the menu panel.  Called from toggle_window,
+# the first time the Menu button is hit.
+#
+proc build.menu { } {
+	set w .menu
+	create_toplevel $w "vic menu"
+	wm withdraw $w
+	catch "wm resizable $w false false"
+
+	frame $w.session
+	frame $w.cb
+	build.xmit $w.cb
+	frame $w.encoder
+	build.encoder $w.encoder
+	frame $w.decoder
+	build.decoder $w.decoder
+	global V
+	set net $V(data-net)
+	build.session $w.session [$net addr] [$net port] \
+		[[srctab local] srcid] [$net ttl] [[srctab local] sdes name]
+
+	button $w.dismiss -text Dismiss -borderwidth 2 -width 8 \
+		-relief raised -anchor c \
+		-command "toggle_window $w" -font [mediumfont]
+
+	# added to catch window close action
+	wm protocol $w WM_DELETE_WINDOW "toggle_window $w"
+
+	pack $w.cb $w.encoder $w.decoder $w.session -padx 6 -fill x
+	pack $w.dismiss -anchor c -pady 4
+
+	if [have_transmit_permission] {
+		selectInitialDevice
+	}
+}
+
+proc defaultDevice {} {
+	set d [resource defaultDevice]
+	if { $d == "" } {
+		set d [resource device]
+	}
+	return $d
+}	
+
+proc selectInitialDevice {} {
+	global videoDevice inputDeviceList
+	set d [defaultDevice]
+	foreach v $inputDeviceList {
+		if { [$v nickname] == "$d" && \
+			[$v attributes] != "disabled" } {
+			set videoDevice $v
+			select_device $v
+			return
+		}
+	}
+	foreach v $inputDeviceList {
+		if { "[$v attributes]" != "disabled" &&
+			"[$v nickname]" != "still" } {
+			set videoDevice $v
+			select_device $v
+			return
+                }
+	}
+}
+
+proc build.session { w dst port srcid ttl name } {
+	set f [smallfont]	
+
+	label $w.title -text Session
+	pack $w.title -fill x
+
+	frame $w.nb -relief sunken -borderwidth 2
+	pack $w.nb -fill x
+
+	frame $w.nb.frame
+	pack append $w.nb \
+		$w.nb.frame { top fillx }
+
+	label $w.nb.frame.info -font $f -anchor w \
+		-text "Dest: $dst   Port: $port  ID: $srcid  TTL: $ttl"
+
+	frame $w.nb.frame.name
+	label $w.nb.frame.name.label -text "Name: " -font $f -anchor e -width 6
+	mk.entry $w.nb.frame.name updateName $name
+	pack $w.nb.frame.name.label -side left
+	pack $w.nb.frame.name.entry -side left -expand 1 -fill x -pady 2
+
+	frame $w.nb.frame.msg
+	label $w.nb.frame.msg.label -text "Note: " -font $f -anchor e -width 6
+	mk.entry $w.nb.frame.msg update_note ""
+	pack $w.nb.frame.msg.label -side left
+	pack $w.nb.frame.msg.entry -side left -expand 1 -fill x -pady 2
+
+	mk.key $w.nb.frame
+
+	frame $w.nb.frame.b
+
+	button $w.nb.frame.b.stats -text "Global Stats" -borderwidth 2 \
+		-anchor c -font $f -command create_global_window
+	button $w.nb.frame.b.members -text Members -borderwidth 2 \
+		-anchor c -font $f -command "toggle_window .srclist"
+
+	pack $w.nb.frame.b.stats $w.nb.frame.b.members \
+		-side left -padx 4 -pady 2 -anchor c
+
+	pack $w.nb.frame.info $w.nb.frame.name $w.nb.frame.msg \
+		$w.nb.frame.key \
+		-fill x -padx 2 -expand 1
+	pack $w.nb.frame.b -pady 2 -anchor c
+}
+
+proc setFillRate { } {
+	global sendingSlides transmitButtonState V
+	if { $transmitButtonState } {
+		if { $sendingSlides } {
+			$V(grabber) fillrate 16
+		} else {
+			$V(grabber) fillrate 2
+		}
+	}
+}
+
+proc updateName { w name } {
+	set name [string trim $name]
+	if { $name != ""} {
+		[srctab local] sdes name $name
+		return 0
+	}
+	return -1
+}
+
+proc update_note { w s } {
+	set s [string trim $s]
+	[srctab local] sdes note $s
+	return 0
+}
+
+proc encoder args {
+	global V
+	if ![info exists V(encoder)] {
+		puts "vic: encoder: no encoder"
+		return
+	}
+	eval $V(encoder) $args
+}
+
+proc grabber args {
+	global V
+	if ![info exists V(grabber)] {
+		# ignore
+		return
+	}
+	eval $V(grabber) $args
+}
+
+proc create_encoder fmt {
+	if { $fmt == "nvdct" } {
+		set encoder [new module nv]
+		$encoder use-dct 1
+	} else {
+		set encoder [new module $fmt]
+	}
+	return $encoder
+}
+
+set transmitButtonState 0
+set logoButtonState 0
+
+proc transmit { } {
+	global logoButton logoButtonState transmitButtonState videoFormat videoDevice V useJPEGforH261 useHardwareComp numEncoderLayers
+	if ![have grabber] {
+		set DA [$videoDevice attributes]
+		set DF [attribute_class $DA format]
+		set DS [attribute_class $DA size]
+
+		# first, see if device can produce bitstream directly
+		# if not, try a transcoder
+		# if that doesn't work, try anything else
+
+		if { [inList $videoFormat $DF] } {
+			if { $videoFormat == "h261" || $videoFormat == "cellb" || $videoFormat == "jpeg"} {
+				# use special hardware tag...
+				set encoder ""
+				if  { $useHardwareComp } {
+					set encoder [create_encoder "$videoFormat/hw"]
+				}
+				if { $encoder == "" } {
+					set encoder [create_encoder "$videoFormat"]
+				}
+			} else {
+				set encoder [create_encoder $videoFormat]
+			}
+			set grabtarget $encoder
+			set grabq ""
+		} elseif { $videoFormat == "h261" && [inList jpeg $DF] && \
+				$useJPEGforH261 } {
+			# just jpeg->h261 at this time
+			set transcoder [new transcoder jpeg/dct]
+			set encoder [new module h261/dct]
+			$transcoder target $encoder
+			set grabtarget $transcoder
+			set grabq "70"
+		} elseif { [inList $videoFormat [device_formats $videoDevice] ] } {
+			set encoder [create_encoder $videoFormat]
+			set grabtarget $encoder
+			set grabq ""
+		}
+
+		$encoder transmitter $V(session)
+
+		$encoder loop_layer [expr {$numEncoderLayers + 1}]
+		
+		set V(encoder) $encoder
+		set ff [$grabtarget frame-format]
+		set V(grabber) [$videoDevice open $ff]
+		# special cases
+		if { $V(grabber) == "" && $ff == "411" } {
+			# try cif instead of 411
+			set V(grabber) [$videoDevice open cif]
+		}
+		if { $V(grabber) == "" } {
+			#XXX
+			puts "Error: grabber=\"\" puts XXX couldn't set up grabber/encoder for $ff->$videoFormat"
+			exit 1
+		}
+		set error [$V(grabber) status]
+		if { $error < 0 } {
+			close_device
+			if { $error == -2 } {
+				#XXX hack: this happens when we tried to open
+				# a jvideo with a non-jpeg format
+				set transmitButtonState 0
+				set logoButtonState 0
+				open_dialog \
+				    "Can't use jvideo with $videoFormat format"
+				select_device $videoDevice
+				return
+			}
+			set transmitButtonState 0
+			set logoButtonState 0
+			open_dialog \
+			    "can't open [$videoDevice nickname] capture device"
+			return
+		}
+		if ![tm_init $V(grabber) $grabtarget] {
+			$V(grabber) target $grabtarget
+		}
+		init_grabber $V(grabber)
+		if { $grabq != "" } {
+			$V(grabber) q $grabq
+		}
+	}
+	if [have capwin] {
+		set w [winfo toplevel $V(capwin)]
+		if $transmitButtonState {
+			wm deiconify $w
+		} else {
+			wm withdraw $w
+		}
+		update idletasks
+	}
+	$V(grabber) send $transmitButtonState
+}
+
+proc close_device {} {
+	global V
+	delete $V(encoder)
+	delete $V(grabber)
+	unset V(grabber) V(encoder)
+	if [info exists V(capwin)] {
+		# delete the C++ object, then destrory the tk window
+		delete $V(capwin)
+		destroy [winfo toplevel $V(capwin)]
+		unset V(capwin)
+	}
+}
+
+proc release_device { } {
+	global transmitButtonState transmitButton
+	global logoButtonState logoButton
+
+	if [have grabber] {
+	
+		if $logoButtonState {
+			$logoButton invoke
+		}
+		logo_quit
+	
+		if $transmitButtonState {
+			$transmitButton invoke
+		}
+		close_device
+	}
+
+}
+
+proc configWinGrabber {} {
+	global configOnTransmit
+	grabber useconfig $configOnTransmit
+}
+
+proc build.buttons w {
+	set f [smallfont]
+	global transmitButton
+	set transmitButton $w.send
+	global logoButton
+	set logoButton $w.logo
+
+	checkbutton $w.send -text "Transmit" \
+		-relief raised -command transmit \
+		-anchor w -variable transmitButtonState -font $f \
+		-state disabled -highlightthickness 0
+#	checkbutton $w.freeze -text "Freeze" \
+#		-relief raised -command "grabber freeze \$freeze" \
+#		-anchor w -variable freeze -font $f \
+#		-highlightthickness 0
+	button $w.release -text "Release" \
+		-relief raised -command release_device \
+		-font $f -highlightthickness 0
+	checkbutton $w.logo -text "Logo" \
+		-relief raised -command logo_transmit \
+		-anchor w -variable logoButtonState -font $f \
+		-state normal -highlightthickness 0
+		
+#	pack $w.send $w.release $w.freeze -fill both
+	pack $w.send $w.release -fill both
+	pack $w.send $w.logo -fill both
+}
+
+proc doNothing { args } {
+}
+
+proc set_bps { w value } {
+	if [have grabber] {
+		grabber bps $value
+	#XXX
+		session data-bandwidth $value
+	}
+	$w configure -text "$value kbps"
+}
+
+proc set_fps { w value } {
+	grabber fps $value
+	$w configure -text "$value fps"
+}
+
+proc build.sliders w {
+	set f [smallfont]
+
+	global V
+	set key $V(session)
+	global ftext btext
+	set ftext($key) "0.0 f/s"
+	set btext($key) "0.0 kb/s"
+
+	frame $w.info
+	label $w.info.label -text "Rate Control" -font $f
+	label $w.info.fps -textvariable ftext($key) -width 6 \
+		-font $f -pady 0 -borderwidth 0
+    label $w.info.bps -textvariable btext($key) -width 8 \
+		-font $f -pady 0 -borderwidth 0
+	pack $w.info.label -side left
+	pack $w.info.bps $w.info.fps -side right
+	
+	frame $w.bps
+	scale $w.bps.scale -orient horizontal -font $f \
+		-showvalue 0 -from 1 -to [option get . maxbw Vic] \
+		-command "set_bps $w.bps.value" -width 12 \
+		-sliderlength 20 \
+		-relief groove
+	label $w.bps.value -font $f -width 8 -anchor w
+
+	frame $w.fps
+	scale $w.fps.scale -font $f -orient horizontal \
+		-showvalue 0 -from 1 -to 30 \
+		-command "set_fps $w.fps.value" -width 12 \
+		-sliderlength 20 \
+		-relief groove
+	label $w.fps.value -font $f -width 8 -anchor w
+
+	pack $w.info -fill x
+	pack $w.bps $w.fps -fill x
+	pack $w.bps.scale -side left -fill x -expand 1
+	pack $w.bps.value -side left -anchor w 
+	pack $w.fps.scale -fill x -side left -expand 1
+	pack $w.fps.value -side left -anchor w
+	
+	$w.bps.scale set [option get . bandwidth Vic]
+	$w.fps.scale set [option get . framerate Vic]
+
+	global fps_slider bps_slider
+	set fps_slider $w.fps.scale
+	set bps_slider $w.bps.scale
+}
+
+proc attribute_class { attr class } {
+	while { [llength $attr] >= 2 } {
+		if { [lindex $attr 0] == $class } {
+			return [lindex $attr 1]
+		}
+		set attr [lrange $attr 2 end]
+	}
+	return ""
+}
+
+proc inList { item L } {
+	foreach v $L {
+		if { $v == $item } {
+			return 1
+		}
+	}
+	return 0
+}
+
+#
+# Returns true iff device named by $device has an attribute named
+# $attr in the attribute class $class.  For example, 
+# "device_supports vl size cif" would return true.
+# if $attr is "*", then returns true iff the indicated $class
+# exists in the attribute list (for example, "device_supports $d port *"
+# says whether a device supports port selection at all)
+#
+proc device_supports { device class attr } {
+	set L [$device attributes]
+	set L [attribute_class $L $class]
+	if { $attr == "*" } {
+		if { $L == "" } {
+			return 0
+		} else {
+			return 1
+		}
+	} else {
+		return [inList $attr $L]
+	}
+}
+
+# device_formats: any type of stream produce-able from this device
+# (not necessarily native)
+proc device_formats device {
+	set L [$device attributes]
+	set sizes [attribute_class $L size]
+	set formats [attribute_class $L format]
+	set fmtList ""
+	if [inList 422 $formats] {
+		set fmtList "$fmtList nv nvdct cellb jpeg raw"
+	}
+	if [inList 411 $formats] {
+		set fmtList "$fmtList bvc pvh"
+	}
+	if [inList cif $sizes] {
+		set fmtList "$fmtList h261 h261as h263+ h263"
+	}
+	if [inList jpeg $formats] {
+		set fmtList "$fmtList jpeg"
+		global useJPEGforH261
+		if $useJPEGforH261 {
+			set fmtList "$fmtList h261"
+		}
+	}
+	return $fmtList
+}
+
+#
+# called when selecting a new device: insert a grabber control panel
+# if it exists and remove the old one (if one was installed)
+#
+proc insert_grabber_panel devname {
+	set k [string first - $devname]
+	if { $k >= 0 } {
+		incr k -1
+		set devname [string range $devname 0 $k]
+	}
+	regsub -all " " $devname "_" devname
+	set w .menu.$devname
+	global grabberPanel
+	if [info exists grabberPanel] {
+		if { "$grabberPanel" == "$w" } {
+			return
+		}
+		pack forget $grabberPanel
+		unset grabberPanel
+	}
+	if { [info procs build.$devname] != "" } {
+		if ![winfo exists $w] {
+			frame $w
+			build.$devname $w
+		}
+		pack $w -before .menu.encoder -padx 6 -fill x
+		set grabberPanel $w
+	}
+}
+
+#
+# Called when use selects a particular device (like videopix or xil)
+# (and at startup for default device)
+#
+proc select_device device {
+	global transmitButton sizeButtons portButton formatButtons \
+		videoFormat defaultFormat lastDevice defaultPort inputPort \
+		transmitButtonState typeButton
+
+	#
+	# Remember settings of various controls for previous device
+	# and close down the device if it's already open
+	#
+	set wasTransmitting $transmitButtonState
+	if [info exists lastDevice] {
+		set defaultFormat($lastDevice) $videoFormat
+		set defaultPort($lastDevice) $inputPort
+		release_device
+	}
+	set lastDevice $device
+
+	set fmtList [device_formats $device]
+	foreach b $formatButtons {
+		set fmt [lindex [$b configure -value] 4]
+		#XXX
+		if { $fmt == "bvc" && ![yesno enableBVC] } {
+			$b configure -state disabled
+		} elseif { [inList $fmt $fmtList] } {
+			$b configure -state normal
+		} else {
+			$b configure -state disabled
+		}
+	}
+	$transmitButton configure -state normal
+	if [device_supports $device size small] {
+		$sizeButtons.b0 configure -state normal
+	} else {
+		$sizeButtons.b0 configure -state disabled
+	}
+	if [device_supports $device size large] {
+		$sizeButtons.b2 configure -state normal
+	} else {
+		$sizeButtons.b2 configure -state disabled
+	}
+	if [device_supports $device port *] {
+		$portButton configure -state normal
+		attach_ports $device
+	} else {
+		$portButton configure -state disabled
+	}
+	if [device_supports $device type *] {
+		$typeButton configure -state normal
+	} else {
+		$typeButton configure -state disabled
+	}
+	insert_grabber_panel [$device nickname]
+
+	set videoFormat $defaultFormat($device)
+	select_format $videoFormat
+	if $wasTransmitting {
+		$transmitButton invoke
+	}
+}
+
+proc build.device w {
+	set f [smallfont]
+
+	set m $w.menu
+	menubutton $w -menu $m -text Device... \
+		-relief raised -width 10 -font $f
+	menu $m
+
+	global defaultFormat inputDeviceList videoFormat
+	set videoFormat [option get . defaultFormat Vic]
+	if { $videoFormat == "h.261" } {
+		set videoFormat h261
+	}
+	#
+	# Disabled the device button if we have no devices or
+	# if we don't have transmit persmission.
+	#
+	if { ![info exists inputDeviceList] || ![have_transmit_permission] } {
+		$w configure -state disabled
+		return
+	}
+	foreach d $inputDeviceList {
+		if { [$d nickname] == "still" && ![yesno stillGrabber] } {
+			set defaultFormat($d) $videoFormat
+			continue
+		}
+		# this is fragile
+		$m add radiobutton -label [$d nickname] \
+			-command "select_device $d" \
+			-value $d -variable videoDevice -font $f
+		if { "[$d attributes]" == "disabled" } {
+			$m entryconfigure [$d nickname] -state disabled
+		}
+		set fmtList [device_formats $d]
+		if [inList $videoFormat $fmtList] {
+			set defaultFormat($d) $videoFormat
+		} else {
+			set defaultFormat($d) [lindex $fmtList 0]
+		}
+	}
+}
+
+proc format_col3 { w n0 n1 n2 } {
+	set f [smallfont]
+	frame $w
+	radiobutton $w.b0 -text $n0 -relief flat -font $f -anchor w \
+		-variable videoFormat -value $n0 -padx 0 -pady 0 \
+		-command "select_format $n0" -state disabled
+	radiobutton $w.b1 -text $n1 -relief flat -font $f -anchor w \
+		-variable videoFormat -value $n1 -padx 0 -pady 0 \
+		-command "select_format $n1" -state disabled
+	radiobutton $w.b2 -text $n2 -relief flat -font $f -anchor w \
+		-variable videoFormat -value $n2 -padx 0 -pady 0 \
+		-command "select_format $n2" -state disabled
+	pack $w.b0 $w.b1 $w.b2 -fill x 
+
+	global formatButtons
+	lappend formatButtons $w.b0 $w.b1 $w.b2
+
+	#format_col $w.p0 nv nvdct cellb 
+	#format_col $w.p1 jpeg h261 bvc
+	#format_col $w.p2 h263+ h263 raw
+}
+
+proc format_col { w n0 n1 } {
+	set f [smallfont]
+	frame $w
+	if { [string first : $n0] > 0 } { 
+		set reliefn0 ridge
+		set n0 [ string range $n0 0 [expr {[string length $n0] -2 }] ]
+	} else {
+		set reliefn0 flat
+	}
+	if { [string first : $n1] > 0 } { 
+		set reliefn1 ridge
+		set n1 [ string range $n1 0 [expr {[string length $n1] -2 }] ]
+	} else {
+		set reliefn1 flat
+	}
+	radiobutton $w.b0 -text $n0 -relief $reliefn0 -font $f -anchor w \
+		-variable videoFormat -value $n0 -padx 0 -pady 0 \
+		-command "select_format $n0" -state disabled
+	radiobutton $w.b1 -text $n1 -relief $reliefn1 -font $f -anchor w \
+		-variable videoFormat -value $n1 -padx 0 -pady 0 \
+		-command "select_format $n1" -state disabled
+	pack $w.b0 $w.b1 -fill x 
+
+	global formatButtons
+	lappend formatButtons $w.b0 $w.b1
+
+	#format_col $w.p0 nv nvdct 
+	#format_col $w.p1 jpeg h261
+	#format_col $w.p2 h263+ h263
+	#format_col $w.p3 raw cellb
+	#format_col $w.p4 pvh bvc
+}
+
+proc set_numEncoderLayers { value } {
+	global transmitButtonState numEncoderLayers V encoderLayerScale encoderLayerValue
+
+	$encoderLayerValue configure -text $value
+	
+	if $transmitButtonState {
+		$V(encoder) loop_layer [expr {$numEncoderLayers + 1}]
+		#$V(decoder) maxChannel $numEncoderLayers
+	}
+}
+
+proc build.encoderLayer_scale w {
+	global numLayers encoderLayerScale encoderLayerValue
+
+	set f [smallfont]
+
+	frame $w.tb
+	label $w.title -text "Layers" -font $f -anchor w
+	label $w.tb.value -text 0 -font $f -width 3
+	scale $w.tb.scale -font $f -orient horizontal \
+		-showvalue 0 -from 0 -to $numLayers \
+		-variable numEncoderLayers \
+		-width 12 -relief groove \
+        -command "set_numEncoderLayers"
+
+
+	set encoderLayerScale $w.tb.scale
+	set encoderLayerValue $w.tb.value
+
+	$encoderLayerValue configure -text $numLayers
+
+#$layerscale configure -state disabled
+
+	pack $w.tb.scale -side left -fill x -expand 1
+	pack $w.tb.value -side left
+	pack $w.title -padx 2 -side left
+	pack $w.tb -fill x -padx 6 -side left -expand 1
+}
+
+proc build.format w {
+	format_col $w.p0 nv nvdct 
+	format_col $w.p1 jpeg h261
+	format_col $w.p2 h263+ h263
+	format_col $w.p3 raw cellb
+	format_col $w.p4 bvc pvh:
+	format_col $w.p5 h261as null
+	
+	frame $w.glue0
+	frame $w.glue1
+	pack $w.p0 $w.p1 $w.p2 $w.p3 $w.p4 $w.p5 -side left
+
+}
+
+proc build.size w {
+	set f [smallfont]
+
+	set b $w.b
+	frame $b
+	radiobutton $b.b0 -text "small" -command "grabber decimate 4" \
+		-padx 0 -pady 0 \
+		-anchor w -variable inputSize -font $f -relief flat -value 4
+	radiobutton $b.b1 -text "normal" -command "grabber decimate 2" \
+		-padx 0 -pady 0 \
+		-anchor w -variable inputSize -font $f -relief flat -value 2
+	radiobutton $b.b2 -text "large" -command "grabber decimate 1" \
+		-padx 0 -pady 0 \
+		-anchor w -variable inputSize -font $f -relief flat -value 1
+	pack $b.b0 $b.b1 $b.b2 -fill x 
+	pack $b -anchor c -side left
+	global inputSize sizeButtons
+	set inputSize 2
+	set sizeButtons $b
+}
+
+proc build.port w {
+	set f [smallfont]
+	# create the menubutton but don't defer the menu creation until later
+	menubutton $w -menu $w.menu -text Port... \
+		-relief raised -width 10 -font $f -state disabled
+	global portButton inputPort
+	set portButton $w
+	set inputPort undefined
+}
+
+proc attach_ports device {
+	global portButton inputPort defaultPort
+	catch "destroy $portButton.menu"
+	set portnames [attribute_class [$device attributes] port]
+	set f [smallfont]
+	set m $portButton.menu
+	menu $m
+	foreach port $portnames {
+		$m add radiobutton -label $port \
+			-command "grabber port $port" \
+			-value $port -variable inputPort -font $f
+	}
+	if ![info exists defaultPort($device)] {
+		set nn [$device nickname]
+		if [info exists defaultPort($nn)] {
+			set defaultPort($device) $defaultPort($nn)
+		} else {
+			set s [resource defaultPort($nn)]
+			if { $s != "" } {
+				set defaultPort($device) $s
+			} else {
+				set defaultPort($device) [lindex $portnames 0]
+			}
+		}
+	}
+	set inputPort $defaultPort($device)
+}
+
+proc build.type w {
+	set f [smallfont]
+
+	set m $w.menu
+	menubutton $w -text Signal... -menu $m -relief raised \
+		-width 10 -font $f -state disabled
+	menu $m
+	$m add radiobutton -label "auto" -command restart \
+		-value auto -variable inputType -font $f
+	$m add radiobutton -label "NTSC" -command restart \
+		-value ntsc -variable inputType -font $f
+	$m add radiobutton -label "PAL" -command restart \
+		-value pal -variable inputType -font $f
+	$m add radiobutton -label "SECAM" -command restart \
+		-value secam -variable inputType -font $f
+
+	global inputType typeButton
+	set inputType auto
+	set typeButton $w
+}
+
+proc build.encoder_buttons w {
+	set f [smallfont]
+	build.encoder_options $w.options
+	build.device $w.device
+	build.port $w.port
+	build.type $w.type
+	pack $w.device $w.port $w.type $w.options -fill x
+}
+
+proc build.encoder_options w {
+	global useJPEGforH261 tcl_platform useHardwareComp
+	set useJPEGforH261 [yesno useJPEGforH261]
+	set useHardwareComp [yesno useHardwareComp]
+	set f [smallfont]
+	set m $w.menu
+	menubutton $w -text Options... -menu $m -relief raised -width 10 \
+		-font $f
+	menu $m
+    	$m add checkbutton -label "Sending Slides" \
+		-variable sendingSlides -font $f -command setFillRate
+    	$m add checkbutton -label "Use JPEG for H261" \
+		-variable useJPEGforH261 -font $f -command restart
+		$m add checkbutton -label "Use Hardware Encode" \
+		-variable useHardwareComp -font $f -command restart
+		if {$tcl_platform(platform) == "windows"} {
+			$m add checkbutton -label "Configure on Transmit" \
+			-variable configOnTransmit -font $f
+		}
+}
+
+proc build.tile w {
+	set f [smallfont]
+	set m $w.menu
+	menubutton $w -text Tile... -menu $m -relief raised -width 10 \
+		-font $f
+	menu $m
+	$m add radiobutton -label Single -command "redecorate 1" \
+		-value 1 -variable V(ncol) -font $f
+	$m add radiobutton -label Double -command "redecorate 2" \
+		-value 2 -variable V(ncol) -font $f
+	$m add radiobutton -label Triple -command "redecorate 3" \
+		-value 3 -variable V(ncol) -font $f
+	$m add radiobutton -label Quad -command "redecorate 4" \
+		-value 4 -variable V(ncol) -font $f
+}
+
+proc build.decoder_options w {
+	set f [smallfont]
+	set m $w.menu
+	menubutton $w -text Options... -menu $m -relief raised -width 10 \
+		-font $f
+	menu $m
+    	$m add checkbutton -label "Mute New Sources" \
+		-variable V(muteNewSources) -font $f
+    	$m add checkbutton -label "Use Hardware Decode" \
+		-variable V(useHardwareDecode) -font $f
+	$m add separator
+    	$m add command -label "Optimize Colormap" \
+		-command fork_histtolut -font $f
+
+	global V
+	set V(optionsMenu) $m
+	if ![have dither] {
+		$m entryconfigure "Optimize Colormap" -state disabled
+	}
+}
+
+proc build.external w {
+	set f [smallfont]
+	set m $w.menu
+	global outputDeviceList
+	if ![info exists outputDeviceList] {
+		set outputDeviceList ""
+	}
+	if { [llength $outputDeviceList] <= 1 } {
+		button $w -text External -relief raised \
+			-width 10 -font $f -highlightthickness 0 \
+			-command "extout_select $outputDeviceList"
+	} else {
+		menubutton $w -text External... -menu $m -relief raised \
+			-width 10 -font $f 
+		menu $m
+		foreach d $outputDeviceList {
+			$m add command -font $f -label [$d nickname] \
+				-command "extout_select $d"
+		}
+	}
+	if { $outputDeviceList == "" } {
+		$w configure -state disabled
+	}
+}
+
+proc build.dither w {
+	set f [smallfont]
+	if [have dither] {
+		set var V(dither)
+		set state normal
+	} else {
+		set var dummyDither
+		set state disabled
+	}
+	set v $w.h0
+	frame $v
+	radiobutton $v.b0 -text "Ordered" -command set_dither \
+		-padx 0 -pady 0 \
+		-anchor w -variable $var -state $state \
+		-font $f -relief flat -value od
+	radiobutton $v.b1 -text "Error Diff" -command set_dither \
+		-padx 0 -pady 0 \
+		-anchor w -variable $var -state $state \
+		-font $f -relief flat -value ed
+	set v $w.h1
+	frame $v
+	radiobutton $v.b2 -text Quantize -command set_dither \
+		-padx 0 -pady 0 \
+		-anchor w -variable $var -state $state \
+		-font $f -relief flat \
+		-value quantize
+	radiobutton $v.b3 -text Gray -command set_dither \
+		-padx 0 -pady 0 \
+		-anchor w -variable $var -state $state \
+		-font $f -relief flat -value gray
+
+	pack $w.h0.b0 $w.h0.b1 -anchor w -fill x
+	pack $w.h1.b2 $w.h1.b3 -anchor w -fill x
+	pack $w.h0 $w.h1 -side left
+}
+
+proc update_gamma { w s } {
+	global V win_src
+	set cm $V(colorModel)
+	if ![$cm gamma $s] {
+		return -1
+	}
+	set V(gamma) $s
+	$cm free-colors
+	if ![$cm alloc-colors] {
+		revert_to_gray
+	}
+	#
+	# Need to update all the windows.  Can't just do a redraw
+	# on all the windows because that won't cause the renderer's
+	# to update their copy of the image (which has the old colormap
+	# installed).  Instead, go through all the active decoders and
+	# force them to update all the windows.
+	# 
+	foreach src [session active] {
+		set d [$src handler]
+		if { $d != "" } {
+			$d redraw
+		}
+	}
+
+	return 0
+}
+
+proc build.gamma w {
+	global V
+	frame $w
+	label $w.label -text "Gamma: " -font [smallfont] -anchor e
+	mk.entry $w update_gamma $V(gamma)
+	$w.entry configure -width 6
+	if ![have dither] {
+		$w.entry configure -state disabled -foreground gray60
+		$w.label configure -foreground gray60
+	}
+	pack $w.label -side left
+	pack $w.entry -side left -expand 1 -fill x -pady 2
+}
+
+proc build.decoder w {
+	set f [smallfont]
+
+	label $w.title -text Display
+	frame $w.f -relief sunken -borderwidth 2
+
+	set v $w.f.h0
+	frame $v
+
+	build.external $v.ext
+	build.tile $v.tile
+	build.decoder_options $v.options
+
+	pack $v.options $v.tile $v.ext -fill x -expand 1
+
+	set v $w.f.h2
+	frame $v
+	frame $v.dither -relief groove -borderwidth 2
+	build.dither $v.dither
+	frame $v.bot
+	build.gamma $v.bot.gamma
+	label $v.bot.mode -text "\[[winfo depth .top]-bit\]" -font $f
+	pack $v.bot.gamma $v.bot.mode -side left -padx 4
+	pack $v.dither $v.bot -anchor c -pady 2
+
+	pack $w.f.h0 -side left -padx 6 -pady 6
+	pack $w.f.h2 -side left -padx 6 -pady 6 -fill x -expand 1
+
+	pack $w.title $w.f -fill x
+}
+
+proc build.encoder w {
+	label $w.title -text Encoder
+	frame $w.f -relief sunken -borderwidth 2
+
+	frame $w.f.h0 -relief flat
+	frame $w.f.quality -relief flat
+	frame $w.f.h0.eb -relief flat
+	frame $w.f.h0.format -relief groove -borderwidth 2
+	frame $w.f.h0.size -relief groove -borderwidth 2
+	frame $w.f.h0.gap -relief flat -width 4
+
+	build.encoder_buttons $w.f.h0.eb
+	build.format $w.f.h0.format
+	build.size $w.f.h0.size
+
+	build.q $w.f.quality
+
+	pack $w.f.h0.eb -side left -anchor n -fill y -padx 6 -pady 4
+	pack $w.f.h0.format -side left -anchor n -fill both -expand 1
+	pack $w.f.h0.size -side left -anchor c -fill both
+	pack $w.f.h0.gap -side left -anchor c
+
+	pack $w.f.h0 -fill x -pady 4
+	pack $w.f.quality -fill x -pady 6
+	pack $w.title $w.f -fill x
+}
+
+proc jpeg_setq value {
+	global useHardwareComp videoDevice
+	incr value
+	if { $value > 95 } {
+		set value 95
+	} elseif { $value < 5 } {
+		set value 5
+	}
+
+	set DA [$videoDevice attributes]
+	set DF [attribute_class $DA format]
+	if { [inList "jpeg" $DF] && $useHardwareComp } {
+		grabber q $value
+	} elseif [have grabber] {
+		encoder q $value
+	}	
+	
+	global qvalue
+	$qvalue configure -text $value
+}
+
+proc h261_setq value {
+	set value [expr int((1 - $value / 100.) * 29) + 1]
+	if [have grabber] {
+		encoder q $value
+	}
+	global qvalue
+	$qvalue configure -text $value
+}
+
+proc h263+_setq value {
+	set value [expr int((1 - $value / 100.) * 29) + 1]
+	if [have grabber] {
+		encoder q $value
+	}
+	global qvalue
+	$qvalue configure -text $value
+}
+
+proc h263_setq value {
+	set value [expr int((1 - $value / 100.) * 29) + 1]
+	if [have grabber] {
+		encoder q $value
+	}
+	global qvalue
+	$qvalue configure -text $value
+}
+
+proc nv_setq value {
+	set value [expr (100 - $value) / 10]
+	if [have grabber] {
+		encoder q $value
+	}
+	global qvalue
+	$qvalue configure -text $value
+}
+
+proc nvdct_setq value {
+	nv_setq $value
+	global qvalue
+	$qvalue configure -text $value
+}
+
+proc raw_setq value {
+	set value 1
+	if [have grabber] {
+		encoder q $value
+	}
+	global qvalue
+	$qvalue configure -text $value
+}
+
+set bvc_quantizer(0) { 0 0 0 0 1 1 1 1 2 2 }
+set bvc_quantizer(1) { 0 0 0 1 1 1 1 1 2 3 }
+set bvc_quantizer(2) { 0 0 0 1 1 1 1 2 3 3 }
+set bvc_quantizer(3) { 0 0 0 1 1 1 2 2 4 4 }
+set bvc_quantizer(4) { 0 0 0 2 2 2 3 3 4 4 }
+set bvc_quantizer(5) { 0 0 0 2 2 2 3 4 4 4 }
+set bvc_quantizer(6) { 0 0 0 2 2 2 4 4 5 5 }
+set bvc_quantizer(7) { 0 0 0 2 3 3 4 5 5 5 }
+set bvc_quantizer(8) { 0 0 0 2 3 4 6 6 6 6 }
+set bvc_quantizer(9) { 2 2 2 3 6 5 7 7 7 7 }
+
+
+proc bvc_setq value {
+	set value [expr 9 - $value / 10]
+	if [have grabber] {
+		global bvc_quantizer
+		set n 0
+		foreach q $bvc_quantizer($value) {
+			encoder q $n [expr 7 - $q]
+			incr n
+		}
+	}
+	global qvalue
+	$qvalue configure -text $value
+}
+
+set pvh_shmap { 0 1 2 1 }
+set pvh_shs {
+	{ lum-dct 0 5-1--11- }
+	{ lum-dct 1 ---5111- }
+	{ lum-dct 2 --51-11- }
+	{ lum-sbc 0 ----4--2 }
+	{ lum-sbc 1 ----4--2 }
+	{ lum-sbc 2 ----4--2 }
+	{ chm     0 -5---1-- }
+	{ chm     1 ---5-1-- }
+	{ chm     2 --5--1-- }
+}
+
+#
+# Format specific routine to map generic quality <i>value</i>
+# into actions that program the underlying PVH codec.
+#
+#VideoPipeline instproc 
+#
+proc pvh_setq value {
+#	$self instvar encoder_
+#	if ![info exists encoder_] {
+#		return -1
+#	}
+	if [have grabber] {
+		#encoder q $value
+
+		#XXX ignore value and just set up the bit allocation
+		#XXX should have variable strategies here
+		global pvh_shmap pvh_shs
+		set n [llength $pvh_shmap]
+		set i 0
+		while { $i < $n } {
+			encoder shmap $i [lindex $pvh_shmap $i]
+			incr i
+		}
+		set i 0
+		foreach tuple $pvh_shs {
+			set compID [lindex $tuple 0]
+			set shID [lindex $tuple 1]
+			set pattern [lindex $tuple 2]
+			encoder comp $compID $shID $pattern
+		}
+		global qvalue
+		$qvalue configure -text $value
+		
+		return 0
+	}
+	#XXX
+	return -1
+}
+
+#
+# If the capture device is open, close it.  If transmission
+# was active fire it up again.  Some state can only be set at
+# device open time, so some controls must resort to this proc.
+#
+proc restart { } {
+	if [have grabber] {
+		global transmitButtonState logoButtonState videoDevice V
+	
+		# HANDLE TRANSMIT LOGO
+		if $logoButtonState {
+			logo_quit
+			logo_transmit
+		} else {
+			logo_quit
+		}
+
+		# HANDLE TRANSMIT VIDEO	
+		if $transmitButtonState {
+			$V(grabber) send 0
+			close_device
+			transmit
+		} else {
+			close_device
+		}
+		
+	}
+}
+
+proc disable_large_button { } {
+	global sizeButtons inputSize
+	if { $inputSize == 1 } {
+		set inputSize 2
+	}
+	$sizeButtons.b2 configure -state disabled
+}
+
+proc enable_large_button { } {
+	global sizeButtons videoDevice
+	if { [info exists videoDevice] && \
+		[device_supports $videoDevice size large] } {
+		$sizeButtons.b2 configure -state normal
+	}
+}
+
+set qscale_val(h261) 68
+set qscale_val(h263) 68
+set qscale_val(h263+) 68
+set qscale_val(nv) 80
+set qscale_val(nvdct) 80
+set qscale_val(bvc) 60
+set qscale_val(jpeg) 29
+set qscale_val(raw) 1
+set lastFmt ""
+
+proc select_format fmt {
+	global qscale qlabel videoDevice videoFormat qscale_val lastFmt
+
+	if { $fmt == "h261" || $fmt == "pvh"} {
+		# H.261 supports only QCIF/CIF
+		disable_large_button
+	} else {
+		enable_large_button
+	}
+
+	if { $fmt == "pvh"} {
+		set w .menu.encoder.f.encoderLayer
+		if ![winfo exists $w] {
+			frame $w
+			build.encoderLayer_scale $w
+		}
+		pack $w -before .menu.encoder.f.quality  -fill x
+	} else {
+		pack forget .menu.encoder.f.encoderLayer
+	}
+
+	set qscale_val($lastFmt) [$qscale get]
+	set lastFmt $videoFormat
+
+	set proc $fmt\_setq
+	if [inList $proc [info commands *_setq]] {
+		$qscale configure -state normal -command $proc
+		$qlabel configure -foreground black
+	} else {
+		$qscale configure -state disabled 
+		$qlabel configure -foreground gray40
+	}
+	set qual [resource quality]
+	if { $qual > 0 } {
+		$qscale set [resource quality]
+	} else { if [info exists qscale_val($fmt)] {
+		$qscale set $qscale_val($fmt)
+	}}
+	if [have grabber] {
+		global V
+		set encoder [create_encoder $videoFormat]
+
+# MM
+#		if { [info procs build.$devname\_$videoFormat] != "" } {
+#			if ![winfo exists $w] {
+#				frame $w
+#				build.$devname $w
+#			}
+#			pack $w -before .menu.encoder -padx 6 -fill x
+#			set grabberPanel $w
+#		}
+# MM
+
+		set ff [$encoder frame-format]
+		if { "$ff" == "[$V(encoder) frame-format]" } {
+			#
+			# new framer has the same format as the
+			# old one.  just replace the old one without
+			# re-initializing the grabber.
+			# XXX doens't work if title-maker is installed
+			#
+			delete $V(encoder)
+			set V(encoder) $encoder
+			$encoder transmitter $V(session)
+			$V(grabber) target $encoder
+		} else {
+			#
+			# Restart the grabber.
+			#
+			delete $encoder
+			restart
+		}
+	}
+}
+
+proc init_grabber { grabber } {
+	global V configOnTransmit tcl_platform
+
+	if {$tcl_platform(platform) == "windows"} {
+		$grabber useconfig $configOnTransmit
+	}
+
+	if { [$grabber need-capwin] && ![have capwin] } {
+		#
+		# we need to create a window for input devices that
+		# require capturing to the frame buffer.  create but
+		# don't map it until after we call "$grabber decimate"
+		# to specify it's size
+		#
+		set rgd [option get . localPlxDisplay $V(class)]
+		if { $rgd != "" } {
+			open_dialog "Using Remote Grabbing Display $rgd"
+			toplevel .capture -class Vic -screen $rgd
+		} else {
+			toplevel .capture -class Vic
+		}
+		wm title .capture "Video Capture Window"
+		$grabber create-capwin .capture.video
+		set V(capwin) .capture.video
+		pack .capture.video
+	    
+		# capture window shouldn't be covered
+		bind .capture <Visibility> "raise .capture"
+	}
+
+	$grabber transmitter $V(session)
+	global qscale inputSize fps_slider bps_slider videoDevice
+	$grabber fps [$fps_slider get]
+	$grabber bps [$bps_slider get]
+	$grabber decimate $inputSize
+	if { [lindex [$qscale configure -state] 4] == "normal" } {
+		set cmd [lindex [$qscale configure -command] 4]
+		$cmd [$qscale get]
+	}
+	global inputPort inputType portButton typeButton
+	if { [$portButton cget -state] == "normal" } {
+		$grabber port $inputPort
+	}
+	if { [$typeButton cget -state] == "normal" } {
+		$grabber type $inputType
+	}
+	setFillRate
+	update
+}
+
+proc build.q w {
+	set f [smallfont]
+	frame $w.tb
+	label $w.title -text "Quality" -font $f -anchor w
+	label $w.tb.value -text 0 -font $f -width 3
+	scale $w.tb.scale -font $f -orient horizontal \
+		-showvalue 0 -from 0 -to 99 \
+		-width 12 -relief groove
+	global qscale qvalue qlabel
+	set qscale $w.tb.scale
+	set qvalue $w.tb.value
+	set qlabel $w.title
+
+	pack $w.tb.scale -side left -fill x -expand 1
+	pack $w.tb.value -side left
+	pack $w.title -padx 2 -side left
+	pack $w.tb -fill x -padx 6 -side left -expand 1
+}
+
+proc build.xmit w {
+	set f [smallfont]
+
+	label $w.label -text Transmission
+	frame $w.frame -relief sunken -borderwidth 2
+	pack $w.label -fill x
+	pack $w.frame -fill both -expand 1
+	frame $w.frame.buttons
+	build.buttons $w.frame.buttons
+	frame $w.frame.right
+	build.sliders $w.frame.right
+	frame $w.frame.tm
+	build.titlemaker $w.frame.tm
+
+	pack $w.frame.buttons -side left -padx 6 
+	pack $w.frame.right -side right -expand 1 -fill x -padx 10 -anchor c
+	pack $w.frame.tm -side top -expand 1 -fill y -pady 10 -anchor c
+	
+}
+
+proc set_dither {} {
+	global win_src
+	set wlist [array names win_src]
+	foreach w $wlist {
+		set ws($w) $win_src($w)
+		detach_window $win_src($w) $w
+	}
+	if ![init_color] {
+		revert_to_gray
+	}
+	foreach w $wlist {
+		attach_window $ws($w) $w
+	}
+}	
+
+proc revert_to_gray {} {
+	global V
+	if { $V(dither) == "gray" } {
+		#XXX
+		puts stderr "vic: out of colors"
+		exit 1
+	}
+	open_dialog "ran out of colors; reverting to gray"
+	set V(dither) gray
+	set_dither
+}
+



More information about the Sumover-dev mailing list