~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Open Mash Cross Reference
mash/codec/encoder-cellb.cc

Component: ~ [ mash ] ~ [ apps ] ~ [ gsm ] ~ [ lib ] ~ [ otcl ] ~ [ srm ] ~ [ tcl8.3 ] ~ [ tclcl ] ~ [ tk8.3 ] ~ [ tutorials ] ~

  1 /*
  2  * encoder-cellb.cc --
  3  *
  4  *      CellB video encoder
  5  */
  6 
  7 /* This code was originally derived from a cellb reference encoder 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/encoder-cellb.cc,v 1.14 2003/11/19 19:20:17 aswan Exp $";
 28 
 29 #include <stdio.h>
 30 #include <stdlib.h>
 31 #include <string.h>
 32 #include <errno.h>
 33 #include "rtp/inet.h"
 34 #include "rtp/rtp.h"
 35 #include "misc/bsd-endian.h"
 36 #include "codec/crdef.h"
 37 #include "rtp/pktbuf-rtp.h"
 38 #include "codec/module.h"
 39 
 40 #define MAXSKIP         32
 41 
 42 extern "C" u_char cellb_yyremap[];
 43 extern "C" u_char cellb_uvremap[];
 44 
 45 #define HLEN (sizeof(rtphdr) + sizeof(cellbhdr))
 46 
 47 class CellbEncoder : public EncoderModule {
 48  public:
 49         CellbEncoder();
 50         ~CellbEncoder();
 51         virtual void recv(Buffer*);
 52  private:
 53         void size(int w, int h);
 54         int diff(const u_char blk1[4], const u_char blk2[4]) const;
 55         void send(pktbuf* pb, int sync, int x, int y, int cc);
 56         u_int encode_cell(const u_char* lum, const u_char* chm, int stride);
 57 
 58         int nw_;
 59         int nh_;
 60 
 61         /*
 62          * Tables for CellB.
 63          */
 64         u_char* divtable_[17];/*FIXME*/
 65         u_char dtbl_[34816];
 66 };
 67 
 68 static class CellbEncoderClass : public TclClass {
 69 public:
 70         CellbEncoderClass() : TclClass("Module/VideoEncoder/Pixel/CellB") {}
 71         TclObject* create(int /* argc */, const char*const* /* argv */) {
 72                 return (new CellbEncoder);
 73         }
 74 } encoder_matcher_cellb;
 75 
 76 void CellbEncoder::send(pktbuf* pb, int sync, int x, int y, int cc)
 77 {
 78         pb->len = cc + HLEN;
 79         rtphdr* rh = (rtphdr*)pb->data;
 80         if (sync)
 81                 rh->rh_flags |= htons(RTP_M);
 82 
 83         cellbhdr* ch = (cellbhdr*)(rh + 1);
 84         ch->width = nw_;
 85         ch->height = nh_;
 86         ch->x = htons(x);
 87         ch->y = htons(y);
 88         target_->recv(pb);
 89 }
 90 
 91 /*
 92  * Returns 32-bit encoded cell in host order.
 93  */
 94 u_int CellbEncoder::encode_cell(const u_char* lum,
 95                                 const u_char* chm,
 96                                 int stride)
 97 {
 98         u_int mask = 0xff00ff;
 99         u_int q0 = *(u_int *)lum;
100         u_int q1 = *(u_int *)&lum[stride];
101         u_int q2 = *(u_int *)&lum[stride << 1];
102         u_int q3 = *(u_int *)&lum[(stride << 1) + stride];
103 
104         /*
105          * Compute the mean of the luminance component.
106          * Do some of the adds in parallel.
107          */
108         u_int ymean = q0 & mask;
109         ymean += (q0 >> 8) & mask;
110         ymean += q1 & mask;
111         ymean += (q1 >> 8) & mask;
112         ymean += q2 & mask;
113         ymean += (q2 >> 8) & mask;
114         ymean += q3 & mask;
115         ymean += (q3 >> 8) & mask;
116         ymean = (ymean & 0xffff) + (ymean >> 16);
117         u_int sum = ymean;
118         ymean >>= 4;
119 
120         /*
121           .... next the bit mask for the tile is generated. for
122           the first fifteen bits this is done by comparing each
123           luminance value to the mean. if that value is greater
124           than the mean the correnponding bit in the mask is set,
125           otherwise the counter for the number of zeros in the mask,
126           tmp, is incremented. also, the values of those pixels less
127           than the mean are accumulted in ylo ....
128           */
129 
130         mask = 0;
131         int ylo = 0;
132         int nb = 0;
133 
134 #define ACCUMULATE(pix, mean, n, slow, mask, pos) \
135         { \
136                 int t = (pix) & 0xff; \
137                 t -= (mean); \
138                 int neg = t >> 31; \
139                 (slow) += neg & t; \
140                 (slow) += neg & (mean); \
141                 neg &= 1; \
142                 (n) += neg; \
143                 (mask) |= neg << (pos); \
144         }
145 #if BYTE_ORDER == LITTLE_ENDIAN
146 #define BYTE(b, n) ((b) >> (8 * (3 - (n))))
147 #else
148 #define BYTE(b, n) ((b) >> (8 * (n)))
149 #endif
150         ACCUMULATE(BYTE(q3, 0), ymean, nb, ylo, mask, 0);
151         ACCUMULATE(BYTE(q3, 1), ymean, nb, ylo, mask, 1);
152         ACCUMULATE(BYTE(q3, 2), ymean, nb, ylo, mask, 2);
153         ACCUMULATE(BYTE(q3, 3), ymean, nb, ylo, mask, 3);
154 
155         ACCUMULATE(BYTE(q2, 0), ymean, nb, ylo, mask, 4);
156         ACCUMULATE(BYTE(q2, 1), ymean, nb, ylo, mask, 5);
157         ACCUMULATE(BYTE(q2, 2), ymean, nb, ylo, mask, 6);
158         ACCUMULATE(BYTE(q2, 3), ymean, nb, ylo, mask, 7);
159 
160         ACCUMULATE(BYTE(q1, 0), ymean, nb, ylo, mask, 8);
161         ACCUMULATE(BYTE(q1, 1), ymean, nb, ylo, mask, 9);
162         ACCUMULATE(BYTE(q1, 2), ymean, nb, ylo, mask, 10);
163         ACCUMULATE(BYTE(q1, 3), ymean, nb, ylo, mask, 11);
164 
165         ACCUMULATE(BYTE(q0, 0), ymean, nb, ylo, mask, 12);
166         ACCUMULATE(BYTE(q0, 1), ymean, nb, ylo, mask, 13);
167         ACCUMULATE(BYTE(q0, 2), ymean, nb, ylo, mask, 14);
168         ACCUMULATE(BYTE(q0, 3), ymean, nb, ylo, mask, 15);
169 #undef BYTE
170 #undef ACCUMULATE
171 
172         int yhi = sum - ylo;
173         yhi = divtable_[16 - nb][yhi];
174         ylo = divtable_[nb][ylo];
175         /*
176          * Normalize bitmask.  Note mask is
177          * computed in negative logic.
178          */
179         if (mask & 0x8000) {
180                 mask ^= 0xffff;
181                 ylo <<= 8;
182                 ylo |= yhi;
183         } else
184                 ylo |= yhi << 8;
185 
186         mask <<= 16;
187 
188         /*
189           .... the high mean and low mean values are finally quantized
190           by the cellb_yyremap[] table, the Y/Y vector codeword byte, the
191           U/V codeword byte and the bitmask are then assembled into
192           a Normal Cell bytecode and returned form the routine ....
193           */
194         mask |= cellb_yyremap[ylo];
195 
196         /*
197          * Simply downsample the chroma components, then
198          * vector quantize according to the CellB spec.
199          * (The encoder in nv computes a mean of the 16
200          * chroma components.  This is probably not a good
201          * idea first because it's computationally more
202          * expensive and second because it doesn't buy
203          * much.  This is equivalent to placing a low-pass
204          * (rectangular) filter in front of the downsampling
205          * stage.  But the chroma signal in most cases
206          * doesn't have much of a high frequency component.
207          * Try visually comparing this coder with nv's.
208          * You will probably see little difference.)
209          */
210         int u = chm[0];
211         int v = chm[framesize_ >> 1];
212         mask |= cellb_uvremap[u >> 2 << 6 | v >> 2] << 8;
213 
214         return (mask);
215 }
216 
217 void CellbEncoder::size(int w, int h)
218 {
219         FrameModule::size(w, h);
220         nw_ = htons(w);
221         nh_ = htons(h);
222 }
223 
224 CellbEncoder::CellbEncoder()
225 {
226         /* .... initialize division table ....  */
227         u_char* p = dtbl_;
228         divtable_[0] = p;
229         for (int i = 1; i <= 16; i++) {
230                 divtable_[i] = p;
231                 for (int j = 0; j < 256*i; j++)
232                         *p++ = j / i;
233         }
234         width_ = 0;
235         height_ = 0;
236         nw_ = 0;
237         nh_ = 0;
238 }
239 
240 CellbEncoder::~CellbEncoder()
241 {
242 }
243 
244 /*
245  * Encode a cellb frame.  this code can be improved by pruning
246  * skip-code runs off the front and back of the frame.
247  */
248 void CellbEncoder::recv(Buffer* bp)
249 {
250         const VideoFrame* vf = (VideoFrame*)bp;
251         if (!samesize(vf))
252                 size(vf->width_, vf->height_);
253         YuvFrame* p = (YuvFrame*)vf;
254 
255         pktbuf* pb = pool_->alloc(p->ts_, RTP_PT_CELLB);
256         u_char* op = &pb->data[HLEN];
257         u_char* ep = op + mtu_ - HLEN;
258         int x0 = 0;
259         int y0 = 0;
260 
261         int cc = 0;
262         int nskip = 0;
263         int stride = 3 * width_;
264 
265         int blkbase = 0;
266         /*
267          * Compute width and height in cells.
268          */
269         int w = width_ >> 2;
270         int h = height_ >> 2;
271 
272         /*
273          * Loop over 4x4 cells, encoding those indicated by the 16x16
274          * CR vector.  Because there are 4 cells per 16x16 replenishment
275          * block, the blocks are incremented only every other interation
276          * of each loop.
277          */
278 
279         const u_int8_t* lum = p->bp_;
280         const u_int8_t* chm = lum + framesize_;
281         const u_int8_t* crvec = p->crvec_;
282         for (int y = 0; y < h; ) {
283                 int blkno = blkbase;
284                 for (int x = 0; x < w; ) {
285                         if (op + 2*5 >= ep) {
286                                 nb_ += cc + HLEN;
287                                 send(pb, 0, x0, y0, cc);
288                                 cc = 0;
289                                 pb = pool_->alloc(p->ts_, RTP_PT_CELLB);
290                                 op = &pb->data[HLEN];
291                                 ep = op + mtu_ - HLEN;
292                                 x0 = x;
293                                 y0 = y;
294                         }
295                         if (crvec[blkno] & CR_SEND) {
296                                 /*
297                                  * cell has seen recent change. send it.
298                                  */
299                                 if (nskip > 0) {
300                                         ++cc;
301                                         *op++ = 0x80 | (nskip - 1);
302                                         nskip = 0;
303                                 }
304                                 int code = encode_cell(lum, chm, width_);
305                                 op[0] = code >> 24;
306                                 op[1] = code >> 16;
307                                 op[2] = code >> 8;
308                                 op[3] = code;
309                                 op += 4;
310                                 cc += 4;
311                         } else {
312                                 if (++nskip >= MAXSKIP) {
313                                         ++cc;
314                                         *op++ = 0x80 | (MAXSKIP - 1);
315                                         nskip = 0;
316                                 }
317                         }
318                         if ((++x & 3) == 0)
319                                 ++blkno;
320                         lum += 4;
321                         chm += 2;
322                 }
323                 if ((++y & 3) == 0)
324                         blkbase += w >> 2;
325 
326                 lum += stride;
327                 chm += stride >> 1;
328         }
329         nb_ += cc;
330         send(pb, 1, x0, y0, cc);
331 }
332 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.