1 /*
2 * decoder-cellb.cc --
3 *
4 * CellB decoder
5 */
6
7 /* This code was originally derived from a cellb reference decoder from
8 * Sun Microsystems with the following copyright:
9 *
10 * Copyright (c) Sun Microsystems, Inc. 1992, 1993. All rights reserved.
11 *
12 * License is granted to copy, to use, and to make and to use derivative
13 * works for research and evaluation purposes, provided that Sun Microsystems is
14 * acknowledged in all documentation pertaining to any such copy or derivative
15 * work. Sun Microsystems grants no other licenses expressed or implied. The
16 * Sun Microsystems trade name should not be used in any advertising without
17 * its written permission.
18 *
19 * SUN MICROSYSTEMS MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF
20 * THIS SOFTWARE FOR ANY PARTICULAR PURPOSE. The software is provided "as is"
21 * without express or implied warranty of any kind.
22 *
23 * These notices must be retained in any copies of any part of this software.
24 */
25
26 static const char rcsid[] =
27 "@(#) $Header: /usr/mash/src/repository/mash/mash-1/codec/decoder-cellb.cc,v 1.11 2003/11/19 19:20:17 aswan Exp $";
28
29 #include <stdio.h>
30 #include <string.h>
31 #include "rtp/inet.h"
32 #include "rtp/rtp.h"
33 #include "codec/decoder.h"
34 #include "misc/bsd-endian.h"
35 #include "net/pktbuf.h"
36
37 class CellbDecoder : public PlaneDecoder {
38 public:
39 CellbDecoder();
40 protected:
41 virtual void recv(pktbuf*);
42 void decode(const u_char*, int cc, int x, int y, int w, int h);
43 };
44
45 static class CellbDecoderClass : public TclClass {
46 public:
47 CellbDecoderClass() : TclClass("Module/VideoDecoder/CellB") {}
48 TclObject* create(int /* argc */, const char*const* /* argv */) {
49 return (new CellbDecoder);
50 }
51 } dm_cellb;
52
53 #define STAT_BAD_GEOM 0
54 #define STAT_BAD_COORD 1
55
56 CellbDecoder::CellbDecoder() : PlaneDecoder(sizeof(cellbhdr))
57 {
58 stat_[STAT_BAD_GEOM].name = "Cellb-Bad-Geom";
59 stat_[STAT_BAD_COORD].name = "Cellb-Bad-Coord";
60 nstat_ = 2;
61
62 color_ = 1;
63 inw_ = 0;
64 inh_ = 0;
65 csss_ = 422;
66 }
67
68 /*
69 * Inverse VQ tables.
70 */
71 extern "C" u_short cellb_yytable[256], cellb_uvtable[256];
72
73 void CellbDecoder::decode(const u_char* p, int cc, int cellx, int celly,
74 int width, int height)
75 {
76 /* Convert width to count in cells */
77 width >>= 2;
78 height >>= 2;
79
80 while (cc >= 4) {
81 int mask = *p;
82 if (mask & 0x80) {
83 cellx += mask - 127;
84 while (cellx >= width) {
85 cellx -= width;
86 ++celly;
87 }
88 ++p;
89 --cc;
90 } else {
91 mask <<= 8;
92 mask |= p[1];
93
94 /*FIXME yytable is backward so flip mask bits*/
95 mask ^= 0xffff;
96 int yy = cellb_yytable[p[3]];
97
98 if (celly >= height) {
99 /*FIXME*/
100 fprintf(stderr, "vic: bad cellb packet\n");
101 return;
102 }
103 int k = 4 * (celly * 4 * width + cellx);
104 u_int* yp = (u_int*)&frm_[k];
105
106 #if BYTE_ORDER == LITTLE_ENDIAN
107 #define MSET(y, yy, mask, pos) \
108 { \
109 int t = (((mask) >> (pos)) & 1) << 3; \
110 y >>= 8; \
111 y |= ((yy) >> t) << 24; \
112 }
113 #else
114 #define MSET(y, yy, mask, pos) \
115 { \
116 int t = (((mask) >> (pos)) & 1) << 3; \
117 y <<= 8; \
118 y |= ((yy) >> t) & 0xff; \
119 }
120 #endif
121 /* First bit of mask is clear. */
122 #if BYTE_ORDER == LITTLE_ENDIAN
123 u_int y = (yy >> 8) << 24;
124 #else
125 u_int y = yy >> 8;
126 #endif
127 MSET(y, yy, mask, 14);
128 MSET(y, yy, mask, 13);
129 MSET(y, yy, mask, 12);
130 *yp = y;
131 yp += width;
132
133 MSET(y, yy, mask, 11);
134 MSET(y, yy, mask, 10);
135 MSET(y, yy, mask, 9);
136 MSET(y, yy, mask, 8);
137 *yp = y;
138 yp += width;
139
140 MSET(y, yy, mask, 7);
141 MSET(y, yy, mask, 6);
142 MSET(y, yy, mask, 5);
143 MSET(y, yy, mask, 4);
144 *yp = y;
145 yp += width;
146
147 MSET(y, yy, mask, 3);
148 MSET(y, yy, mask, 2);
149 MSET(y, yy, mask, 1);
150 MSET(y, yy, mask, 0);
151 *yp = y;
152 #undef MSET
153 int s = (width << 2) * (height << 2);/*FIXME*/
154 u_char* up = frm_ + s + k / 2;
155 u_char* vp = up + (s >> 1);
156
157 k = p[2];
158 int uv = cellb_uvtable[k];
159 int t = uv >> 8;
160 t |= t << 8;
161 *(u_short*)up = t; up += width << 1;
162 *(u_short*)up = t; up += width << 1;
163 *(u_short*)up = t; up += width << 1;
164 *(u_short*)up = t;
165 t = uv & 0xff;
166 t |= t << 8;
167 *(u_short*)vp = t; vp += width << 1;
168 *(u_short*)vp = t; vp += width << 1;
169 *(u_short*)vp = t; vp += width << 1;
170 *(u_short*)vp = t;
171
172 /* mark block as changed */
173 /*FIXME should maintain offset using loop */
174 int o = (cellx >> 1) + (celly >> 1) * (width >> 1);
175 rvts_[o] = now_;
176
177 if (++cellx >= width) {
178 cellx -= width;
179 ++celly;
180 }
181 p += 4;
182 cc -= 4;
183 }
184 ndblk_++;
185 }
186 }
187
188 void CellbDecoder::recv(pktbuf* pb)
189 {
190 rtphdr* rh = (rtphdr*)pb->dp;
191 cellbhdr* ph = (cellbhdr*)(rh + 1);
192 int w = ntohs(ph->width) & 0x7fff;
193 int h = ntohs(ph->height);
194 if (w != inw_ || h != inh_) {
195 if ((unsigned)w > 1000 || (unsigned)h > 1000) {
196 /*FIXME*/
197 w = 320;
198 h = 240;
199 count(STAT_BAD_GEOM);
200 }
201 resize(w, h);
202 }
203 int cc = pb->len - (sizeof(*rh) + sizeof(*ph));
204 decode((u_char*)(ph + 1), cc, ntohs(ph->x), ntohs(ph->y), w, h);
205 if (ntohs(rh->rh_flags) & RTP_M) {
206 render_frame(frm_);
207 resetndblk();
208 }
209 pb->release();
210 }
211
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.