[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