/* * Copyright (c) 1993-1994 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. */ /* This code was originally derived from a cellb reference decoder from * Sun Microsystems with the following copyright: * * Copyright (c) Sun Microsystems, Inc. 1992, 1993. All rights reserved. * * License is granted to copy, to use, and to make and to use derivative * works for research and evaluation purposes, provided that Sun Microsystems is * acknowledged in all documentation pertaining to any such copy or derivative * work. Sun Microsystems grants no other licenses expressed or implied. The * Sun Microsystems trade name should not be used in any advertising without * its written permission. * * SUN MICROSYSTEMS MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF * THIS SOFTWARE FOR ANY PARTICULAR PURPOSE. The software is provided "as is" * without express or implied warranty of any kind. * * These notices must be retained in any copies of any part of this software. */ static const char rcsid[] = "@(#) $Header: /cs/research/mice/starship/src/local/CVS_repository/vic/codec/decoder-cellb.cpp,v 1.2 1999/11/05 11:33:03 piers Exp $ (LBL)"; #include #include #include "inet.h" #include "rtp.h" #include "decoder.h" #include "bsd-endian.h" #include "pktbuf.h" class CellbDecoder : public PlaneDecoder { public: CellbDecoder(); protected: virtual void recv(pktbuf*); void decode(const u_char*, int cc, int x, int y, int w, int h); }; static class CellbDecoderMatcher : public Matcher { public: CellbDecoderMatcher() : Matcher("decoder") {} TclObject* match(const char* id) { if (strcasecmp(id, "cellb") == 0) return (new CellbDecoder()); else return (0); } } dm_cellb; #define STAT_BAD_GEOM 0 #define STAT_BAD_COORD 1 CellbDecoder::CellbDecoder() : PlaneDecoder(sizeof(cellbhdr)) { stat_[STAT_BAD_GEOM].name = "Cellb-Bad-Geom"; stat_[STAT_BAD_COORD].name = "Cellb-Bad-Coord"; nstat_ = 2; color_ = 1; inw_ = 0; inh_ = 0; } /* * Inverse VQ tables. */ extern "C" u_short cellb_yytable[256], cellb_uvtable[256]; void CellbDecoder::decode(const u_char* p, int cc, int cellx, int celly, int width, int height) { /* Convert width to count in cells */ width >>= 2; height >>= 2; while (cc >= 4) { int mask = *p; if (mask & 0x80) { cellx += mask - 127; while (cellx >= width) { cellx -= width; ++celly; } ++p; --cc; } else { mask <<= 8; mask |= p[1]; /*XXX yytable is backward so flip mask bits*/ mask ^= 0xffff; int yy = cellb_yytable[p[3]]; if (celly >= height) { /*XXX*/ fprintf(stderr, "vic: bad cellb packet\n"); return; } int k = 4 * (celly * 4 * width + cellx); u_int* yp = (u_int*)&frm_[k]; #if BYTE_ORDER == LITTLE_ENDIAN #define MSET(y, yy, mask, pos) \ { \ int t = (((mask) >> (pos)) & 1) << 3; \ y >>= 8; \ y |= ((yy) >> t) << 24; \ } #else #define MSET(y, yy, mask, pos) \ { \ int t = (((mask) >> (pos)) & 1) << 3; \ y <<= 8; \ y |= ((yy) >> t) & 0xff; \ } #endif /* First bit of mask is clear. */ #if BYTE_ORDER == LITTLE_ENDIAN u_int y = (yy >> 8) << 24; #else u_int y = yy >> 8; #endif MSET(y, yy, mask, 14); MSET(y, yy, mask, 13); MSET(y, yy, mask, 12); *yp = y; yp += width; MSET(y, yy, mask, 11); MSET(y, yy, mask, 10); MSET(y, yy, mask, 9); MSET(y, yy, mask, 8); *yp = y; yp += width; MSET(y, yy, mask, 7); MSET(y, yy, mask, 6); MSET(y, yy, mask, 5); MSET(y, yy, mask, 4); *yp = y; yp += width; MSET(y, yy, mask, 3); MSET(y, yy, mask, 2); MSET(y, yy, mask, 1); MSET(y, yy, mask, 0); *yp = y; #undef MSET int s = (width << 2) * (height << 2);/*XXX*/ u_char* up = frm_ + s + k / 2; u_char* vp = up + (s >> 1); k = p[2]; int uv = cellb_uvtable[k]; int t = uv >> 8; t |= t << 8; *(u_short*)up = t; up += width << 1; *(u_short*)up = t; up += width << 1; *(u_short*)up = t; up += width << 1; *(u_short*)up = t; t = uv & 0xff; t |= t << 8; *(u_short*)vp = t; vp += width << 1; *(u_short*)vp = t; vp += width << 1; *(u_short*)vp = t; vp += width << 1; *(u_short*)vp = t; /* mark block as changed */ /*XXX should maintain offset using loop */ int o = (cellx >> 1) + (celly >> 1) * (width >> 1); rvts_[o] = now_; if (++cellx >= width) { cellx -= width; ++celly; } p += 4; cc -= 4; } ndblk_++; } } void CellbDecoder::recv(pktbuf* pb) { rtphdr* rh = (rtphdr*)pb->dp; cellbhdr* ph = (cellbhdr*)(rh + 1); int w = ntohs(ph->width) & 0x7fff; int h = ntohs(ph->height); if (w != inw_ || h != inh_) { if ((unsigned)w > 1000 || (unsigned)h > 1000) { /*XXX*/ w = 320; h = 240; count(STAT_BAD_GEOM); } resize(w, h); } int cc = pb->len - (sizeof(*rh) + sizeof(*ph)); decode((u_char*)(ph + 1), cc, ntohs(ph->x), ntohs(ph->y), w, h); if (ntohs(rh->rh_flags) & RTP_M) { render_frame(frm_); resetndblk(); } pb->release(); }