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

Open Mash Cross Reference
mash/codec/decoder-nv.cc

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

  1 /*
  2  * decoder-nv.cc --
  3  *
  4  *      Netvideo decoder
  5  */
  6 
  7 /*
  8  * This module was originally derived from:
  9  *
 10  * Netvideo version 3.2
 11  * Written by Ron Frederick <frederick@parc.xerox.com>
 12  *
 13  * Video decode routines
 14  *
 15  * Copyright (c) Xerox Corporation 1992. All rights reserved.
 16  *
 17  * License is granted to copy, to use, and to make and to use derivative
 18  * works for research and evaluation purposes, provided that Xerox is
 19  * acknowledged in all documentation pertaining to any such copy or derivative
 20  * work. Xerox grants no other licenses expressed or implied. The Xerox trade
 21  * name should not be used in any advertising without its written permission.
 22  *
 23  * XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE
 24  * MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE
 25  * FOR ANY PARTICULAR PURPOSE.  The software is provided "as is" without
 26  * express or implied warranty of any kind.
 27  *
 28  * These notices must be retained in any copies of any part of this software.
 29  */
 30 
 31 static const char rcsid[] =
 32     "@(#) $Header: /usr/mash/src/repository/mash/mash-1/codec/decoder-nv.cc,v 1.10 2003/11/19 19:20:17 aswan Exp $";
 33 
 34 #include <stdio.h>
 35 #include <string.h>
 36 #include "rtp/inet.h"
 37 #include "rtp/rtp.h"
 38 #include "codec/decoder.h"
 39 #include "net/pktbuf.h"
 40 
 41 class NvDecoder : public PlaneDecoder {
 42 public:
 43         NvDecoder();
 44 protected:
 45         void info(char* wrk) const;
 46         virtual void recv(pktbuf*);
 47         const u_char* decode_run(const u_char* data, const u_char* end,
 48                                  int color);
 49         void VidTransform_Rev(u_int* inp, u_char* yp, char* up, char* vp,
 50                               int width);
 51         void NVDCT_RevTransform(u_int* inp, u_char *yp,
 52                                 char* up, char* vp, int width);
 53         int use_dct_;
 54 };
 55 
 56 static class NvDecoderClass : public TclClass {
 57 public:
 58         NvDecoderClass() : TclClass("Module/VideoDecoder/NV") {}
 59         TclObject* create(int /* argc */, const char*const* /* argv */) {
 60                 return (new NvDecoder());
 61         }
 62 } dm_nv;
 63 
 64 #define STAT_BAD_GEOM   0
 65 #define STAT_BAD_COORD  1
 66 #define STAT_BAD_BLKRUN 2
 67 #define STAT_BAD_RUNLEN 3
 68 #define STAT_BAD_ENC    4
 69 
 70 NvDecoder::NvDecoder() : PlaneDecoder(sizeof(nvhdr)), use_dct_(0)
 71 {
 72         stat_[STAT_BAD_GEOM].name = "Nv-Bad-Geom";
 73         stat_[STAT_BAD_COORD].name = "Nv-Bad-Coord";
 74         stat_[STAT_BAD_BLKRUN].name = "Nv-Bad-Blkrun";
 75         stat_[STAT_BAD_RUNLEN].name = "Nv-Bad-Runlen";
 76         stat_[STAT_BAD_ENC].name = "Nv-Bad-Enc";
 77         nstat_ = 5;
 78 
 79         inw_ = 0;
 80         inh_ = 0;
 81         csss_ = 422;
 82 
 83 }
 84 void NvDecoder::info(char* wrk) const
 85 {
 86         strcpy(wrk, use_dct_ ? "[dct]" : "[haar]");
 87 }
 88 
 89 /* Sick little macro which will limit x to [0..255] with logical ops */
 90 #define UCLIMIT(x) ((t = (x)), (t &= ~(t>>31)), (t | ~((t-256) >> 31)))
 91 /* A variant of above which will limit x to [-128..127] */
 92 #define SCLIMIT(x) (UCLIMIT((x)+128)-128)
 93 
 94 void NvDecoder::VidTransform_Rev(u_int* inp, u_char *yp,
 95                                  char* up, char* vp, int width)
 96 {
 97     register int i, t, t0, t1, t2, t3, t4, t5, *dataptr;
 98     register int width2=2*width, width6=6*width;
 99     register signed char *inpcptr=(signed char *)inp;
100     static int block[64];
101 #define SIGN_EXTEND(c) c
102 
103     dataptr = block;
104     for (i=0; i<8; i++) {
105         if ((inp[0] << 8) == 0) {
106             t2 = t3 = t4 = t5 = SIGN_EXTEND(inpcptr[0]);
107         } else {
108             t4 = SIGN_EXTEND(inpcptr[0]);
109             t5 = SIGN_EXTEND(inpcptr[1]);
110             t0 = t4 - t5;
111             t1 = t4 + t5;
112 
113             t4 = SIGN_EXTEND(inpcptr[2]);
114             t5 = SIGN_EXTEND(inpcptr[3]);
115             t2 = t0 - t4;
116             t3 = t0 + t4;
117             t4 = t1 - t5;
118             t5 = t1 + t5;
119         }
120 
121         if (inp[1] == 0) {
122             dataptr[0] = dataptr[1] = t2;
123             dataptr[2] = dataptr[3] = t3;
124             dataptr[4] = dataptr[5] = t4;
125             dataptr[6] = dataptr[7] = t5;
126         } else {
127             t0 = SIGN_EXTEND(inpcptr[4]);
128             t1 = SIGN_EXTEND(inpcptr[5]);
129             dataptr[0] = t2 - t0;
130             dataptr[1] = t2 + t0;
131             dataptr[2] = t3 - t1;
132             dataptr[3] = t3 + t1;
133 
134             t0 = SIGN_EXTEND(inpcptr[6]);
135             t1 = SIGN_EXTEND(inpcptr[7]);
136             dataptr[4] = t4 - t0;
137             dataptr[5] = t4 + t0;
138             dataptr[6] = t5 - t1;
139             dataptr[7] = t5 + t1;
140         }
141 
142         inp += 2;
143         inpcptr += 8;
144         dataptr += 8;
145     }
146 
147     dataptr = block;
148     for (i=0; i<8; i++) {
149         t4 = dataptr[0] + 128; /* Add back DC offset */
150         t5 = dataptr[8];
151         t0 = t4 - t5;
152         t1 = t4 + t5;
153 
154         t4 = dataptr[16];
155         t5 = dataptr[24];
156         t2 = t0 - t4;
157         t3 = t0 + t4;
158         t4 = t1 - t5;
159         t5 = t1 + t5;
160 
161         t0 = dataptr[32];
162         t1 = dataptr[40];
163         yp[0] = UCLIMIT(t2 - t0);
164         yp[width] = UCLIMIT(t2 + t0);
165         yp += width2;
166         yp[0] = UCLIMIT(t3 - t1);
167         yp[width] = UCLIMIT(t3 + t1);
168         yp += width2;
169 
170         t0 = dataptr[48];
171         t1 = dataptr[56];
172         yp[0] = UCLIMIT(t4 - t0);
173         yp[width] = UCLIMIT(t4 + t0);
174         yp += width2;
175         yp[0] = UCLIMIT(t5 - t1);
176         yp[width] = UCLIMIT(t5 + t1);
177         yp -= width6;
178 
179         yp++;
180         dataptr++;
181     }
182 
183     if (up) {
184         int uswitch = 1;
185         signed char* p = (signed char*)up++;
186         dataptr = block;
187         for (i=0; i<8; i++) {
188             if ((inp[0] << 16) == 0) {
189                 t2 = t3 = SIGN_EXTEND(inpcptr[0]);
190                 t4 = t5 = SIGN_EXTEND(inpcptr[1]);
191             } else {
192                 t0 = SIGN_EXTEND(inpcptr[0]);
193                 t1 = SIGN_EXTEND(inpcptr[1]);
194 
195                 t4 = SIGN_EXTEND(inpcptr[2]);
196                 t5 = SIGN_EXTEND(inpcptr[3]);
197                 t2 = t0 - t4;
198                 t3 = t0 + t4;
199                 t4 = t1 - t5;
200                 t5 = t1 + t5;
201             }
202 
203             if (inp[1] == 0) {
204                 dataptr[0] = dataptr[2] = t2;
205                 dataptr[4] = dataptr[6] = t3;
206                 dataptr[1] = dataptr[3] = t4;
207                 dataptr[5] = dataptr[7] = t5;
208             } else {
209                 t0 = SIGN_EXTEND(inpcptr[4]);
210                 t1 = SIGN_EXTEND(inpcptr[5]);
211                 dataptr[0] = t2 - t0;
212                 dataptr[2] = t2 + t0;
213                 dataptr[4] = t3 - t1;
214                 dataptr[6] = t3 + t1;
215 
216                 t0 = SIGN_EXTEND(inpcptr[6]);
217                 t1 = SIGN_EXTEND(inpcptr[7]);
218                 dataptr[1] = t4 - t0;
219                 dataptr[3] = t4 + t0;
220                 dataptr[5] = t5 - t1;
221                 dataptr[7] = t5 + t1;
222             }
223 
224             inp += 2;
225             inpcptr += 8;
226             dataptr += 8;
227         }
228 
229         dataptr = block;
230         for (i=0; i<8; i++) {
231             t4 = dataptr[0];
232             t5 = dataptr[8];
233             t0 = t4 - t5;
234             t1 = t4 + t5;
235 
236             t4 = dataptr[16];
237             t5 = dataptr[24];
238             t2 = t0 - t4;
239             t3 = t0 + t4;
240             t4 = t1 - t5;
241             t5 = t1 + t5;
242 
243             t0 = dataptr[32];
244             t1 = dataptr[40];
245 
246             *p = SCLIMIT(t2 - t0) + 0x80;
247             p += width / 2;
248             *p = SCLIMIT(t2 + t0) + 0x80;
249             p += width / 2;
250             *p = SCLIMIT(t3 - t1) + 0x80;
251             p += width / 2;
252             *p = SCLIMIT(t3 + t1) + 0x80;
253             p += width / 2;
254 
255             t0 = dataptr[48];
256             t1 = dataptr[56];
257             *p = SCLIMIT(t4 - t0) + 0x80;
258             p += width / 2;
259             *p = SCLIMIT(t4 + t0) + 0x80;
260             p += width / 2;
261             *p = SCLIMIT(t5 - t1) + 0x80;
262             p += width / 2;
263             *p = SCLIMIT(t5 + t1) + 0x80;
264             p += width / 2;
265 
266             if (uswitch) {
267                     uswitch = 0;
268                     p = (signed char*)vp++;
269             } else {
270                     uswitch = 1;
271                     p = (signed char*)up++;
272             }
273             dataptr++;
274         }
275     }
276 }
277 
278 void NvDecoder::NVDCT_RevTransform(u_int* inp, u_char *yp,
279                                    char* up, char* vp, int width)
280 {
281     int i, t, *dataptr;
282     int a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3;
283     int8_t *inpcptr=(int8_t *)inp;
284     static int block[64];
285 
286     dataptr = block;
287     for (i=0; i<8; i++) {
288         if ((inp[0]|inp[1]) == 0) {
289             dataptr[0] = dataptr[1] = dataptr[2] = dataptr[3] =
290                 dataptr[4] = dataptr[5] = dataptr[6] = dataptr[7] = 0;
291         } else {
292             b0 = inpcptr[0] << 4;
293             b1 = inpcptr[4] << 4;
294             b2 = inpcptr[2] << 4;
295             b3 = inpcptr[6] << 4;
296 
297             a0 = (362 * (b0+b1)) >> 9;
298             a1 = (362 * (b0-b1)) >> 9;
299             a2 = (196*b2 - 473*b3) >> 9;
300             a3 = (473*b2 + 196*b3) >> 9;
301 
302             b0 = a0+a3;
303             b1 = a1+a2;
304             b2 = a1-a2;
305             b3 = a0-a3;
306 
307             a0 = inpcptr[1] << 4;
308             a1 = inpcptr[3] << 4;
309             a2 = inpcptr[5] << 4;
310             a3 = inpcptr[7] << 4;
311 
312             c0 = (100*a0 - 502*a3) >> 9;
313             c1 = (426*a2 - 284*a1) >> 9;
314             c2 = (426*a1 + 284*a2) >> 9;
315             c3 = (502*a0 + 100*a3) >> 9;
316 
317             a0 = c0+c1;
318             a1 = c0-c1;
319             a2 = c3-c2;
320             a3 = c3+c2;
321 
322             c0 = a0;
323             c1 = (362 * (a2-a1)) >> 9;
324             c2 = (362 * (a1+a2)) >> 9;
325             c3 = a3;
326 
327             dataptr[0] = b0+c3;
328             dataptr[1] = b1+c2;
329             dataptr[2] = b2+c1;
330             dataptr[3] = b3+c0;
331             dataptr[4] = b3-c0;
332             dataptr[5] = b2-c1;
333             dataptr[6] = b1-c2;
334             dataptr[7] = b0-c3;
335         }
336 
337         inp += 2;
338         inpcptr += 8;
339         dataptr += 8;
340     }
341 
342     dataptr = block;
343     for (i=0; i<8; i++) {
344         b0 = dataptr[0]+1448; /* Add back DC offset */
345         b1 = dataptr[32];
346         b2 = dataptr[16];
347         b3 = dataptr[48];
348 
349         a0 = (362 * (b0+b1)) >> 9;
350         a1 = (362 * (b0-b1)) >> 9;
351         a2 = (196*b2 - 473*b3) >> 9;
352         a3 = (473*b2 + 196*b3) >> 9;
353 
354         b0 = a0+a3;
355         b1 = a1+a2;
356         b2 = a1-a2;
357         b3 = a0-a3;
358 
359         a0 = dataptr[8];
360         a1 = dataptr[24];
361         a2 = dataptr[40];
362         a3 = dataptr[56];
363 
364         c0 = (100*a0 - 502*a3) >> 9;
365         c1 = (426*a2 - 284*a1) >> 9;
366         c2 = (426*a1 + 284*a2) >> 9;
367         c3 = (502*a0 + 100*a3) >> 9;
368 
369         a0 = c0+c1;
370         a1 = c0-c1;
371         a2 = c3-c2;
372         a3 = c3+c2;
373 
374         c0 = a0;
375         c1 = (362 * (a2-a1)) >> 9;
376         c2 = (362 * (a2+a1)) >> 9;
377         c3 = a3;
378 
379         yp[0]     = UCLIMIT((b0+c3+4) >> 3);
380         yp[width] = UCLIMIT((b1+c2+4) >> 3);
381         yp += 2*width;
382 
383         yp[0]     = UCLIMIT((b2+c1+4) >> 3);
384         yp[width] = UCLIMIT((b3+c0+4) >> 3);
385         yp += 2*width;
386 
387         yp[0]     = UCLIMIT((b3-c0+4) >> 3);
388         yp[width] = UCLIMIT((b2-c1+4) >> 3);
389         yp += 2*width;
390 
391         yp[0]     = UCLIMIT((b1-c2+4) >> 3);
392         yp[width] = UCLIMIT((b0-c3+4) >> 3);
393         yp -= 6*width;
394 
395         yp++;
396         dataptr++;
397     }
398 
399     if (up) {
400         u_int8_t uvblk[64];
401         u_int8_t* uvp = uvblk;
402 #define width 8
403         dataptr = block;
404         for (i=0; i<8; i++) {
405             if ((inp[0]|inp[1]) == 0) {
406                 dataptr[0] = dataptr[1] = dataptr[2] = dataptr[3] =
407                     dataptr[4] = dataptr[5] = dataptr[6] = dataptr[7] = 0;
408             } else {
409                 b0 = inpcptr[0] << 4;
410                 b2 = inpcptr[2] << 4;
411                 b1 = inpcptr[4] << 4;
412                 b3 = inpcptr[6] << 4;
413 
414                 a0 = (362 * (b0+b1)) >> 9;
415                 a1 = (362 * (b0-b1)) >> 9;
416                 a2 = (196*b2 - 473*b3) >> 9;
417                 a3 = (473*b2 + 196*b3) >> 9;
418 
419                 dataptr[0] = a0+a3;
420                 dataptr[2] = a1+a2;
421                 dataptr[4] = a1-a2;
422                 dataptr[6] = a0-a3;
423 
424                 b0 = inpcptr[1] << 4;
425                 b2 = inpcptr[3] << 4;
426                 b1 = inpcptr[5] << 4;
427                 b3 = inpcptr[7] << 4;
428 
429                 a0 = (362 * (b0+b1)) >> 9;
430                 a1 = (362 * (b0-b1)) >> 9;
431                 a2 = (196*b2 - 473*b3) >> 9;
432                 a3 = (473*b2 + 196*b3) >> 9;
433 
434                 dataptr[1] = a0+a3;
435                 dataptr[3] = a1+a2;
436                 dataptr[5] = a1-a2;
437                 dataptr[7] = a0-a3;
438             }
439 
440             inp += 2;
441             inpcptr += 8;
442             dataptr += 8;
443         }
444 
445         dataptr = block;
446         for (i=0; i<8; i++) {
447             b0 = dataptr[0];
448             b1 = dataptr[32];
449             b2 = dataptr[16];
450             b3 = dataptr[48];
451 
452             a0 = (362 * (b0+b1)) >> 9;
453             a1 = (362 * (b0-b1)) >> 9;
454             a2 = (196*b2 - 473*b3) >> 9;
455             a3 = (473*b2 + 196*b3) >> 9;
456 
457             b0 = a0+a3;
458             b1 = a1+a2;
459             b2 = a1-a2;
460             b3 = a0-a3;
461 
462             a0 = dataptr[8];
463             a1 = dataptr[24];
464             a2 = dataptr[40];
465             a3 = dataptr[56];
466 
467             c0 = (100*a0 - 502*a3) >> 9;
468             c1 = (426*a2 - 284*a1) >> 9;
469             c2 = (426*a1 + 284*a2) >> 9;
470             c3 = (502*a0 + 100*a3) >> 9;
471 
472             a0 = c0+c1;
473             a1 = c0-c1;
474             a2 = c3-c2;
475             a3 = c3+c2;
476 
477             c0 = a0;
478             c1 = (362 * (a2-a1)) >> 9;
479             c2 = (362 * (a2+a1)) >> 9;
480             c3 = a3;
481 
482             uvp[0]     = SCLIMIT((b0+c3+4) >> 3);
483             uvp[width] = SCLIMIT((b1+c2+4) >> 3);
484             uvp += 2*width;
485 
486             uvp[0]     = SCLIMIT((b2+c1+4) >> 3);
487             uvp[width] = SCLIMIT((b3+c0+4) >> 3);
488             uvp += 2*width;
489 
490             uvp[0]     = SCLIMIT((b3-c0+4) >> 3);
491             uvp[width] = SCLIMIT((b2-c1+4) >> 3);
492             uvp += 2*width;
493 
494             uvp[0]     = SCLIMIT((b1-c2+4) >> 3);
495             uvp[width] = SCLIMIT((b0-c3+4) >> 3);
496             uvp -= 6*width;
497 
498             uvp++;
499             dataptr++;
500         }
501 #undef width
502         uvp = uvblk;
503         for (i = 0; i < 8; ++i) {
504                 up[0] = uvp[0] + 0x80;
505                 vp[0] = uvp[1] + 0x80;
506                 up[1] = uvp[2] + 0x80;
507                 vp[1] = uvp[3] + 0x80;
508                 up[2] = uvp[4] + 0x80;
509                 vp[2] = uvp[5] + 0x80;
510                 up[3] = uvp[6] + 0x80;
511                 vp[3] = uvp[7] + 0x80;
512                 up += width >> 1;
513                 vp += width >> 1;
514                 uvp += 8;
515         }
516     }
517 }
518 
519 #define VIDCODE_COLORFLAG 0x8000
520 #define VIDCODE_WIDTHMASK 0x0fff
521 
522 const u_char* NvDecoder::decode_run(const u_char* data, const u_char* end,
523                                     int color)
524 {
525         if (end - data < 3)
526                 return (end);
527 
528         int w0, w;
529         w0 = w = *data++;
530         int x0 = *data++;
531         int y0 = *data++;
532 
533         int inw = inw_;
534         int inh = inh_;
535         if ((x0+w > inw/8) || (y0 >= inh/8)) {
536                 count(STAT_BAD_COORD);
537 #ifdef notdef
538                 fprintf(stderr, "vic: bogus offset in nv stream (%d,%d)\n",
539                         x0 + w, y0);
540 #endif
541                 return (end);
542         }
543 
544         int offset = y0 * inw;
545         u_char* ts = &rvts_[(offset >> 3) + x0];
546         offset = (offset << 3) + (x0 << 3);
547         u_char* yp = &frm_[offset];
548         int s = inw * inh;/*FIXME*/
549         u_char* up = frm_ + s + (offset >> 1);
550         u_char* vp = up + (s >> 1);
551         while (w-- > 0) {
552                 if (data >= end) {
553                         count(STAT_BAD_BLKRUN);
554                         return (end);
555                 }
556                 static u_int block[32];
557                 int lim=color? 128 : 64;
558                 for (int i=0; i<lim; ) {
559                         int run = *data++;
560                         int j = run >> 6;
561                         int k = run & 0x3f;
562                         if (i+j+k > lim) {
563 #ifdef notdef
564                                 fprintf(stderr,
565                         "vic: bogus run length in nv stream (%d %d %d %d %d)\n",
566                                         i, j, k, lim, end - data);
567 #endif
568                                 count(STAT_BAD_RUNLEN);
569                                 return (end);
570                         }
571                         char* blkp = (char*)block;
572                         while (j--) blkp[i++] = (char) *data++;
573                         while (k--) blkp[i++] = 0;
574                         ndblk_++;
575                 }
576                 if (use_dct_)
577                         NVDCT_RevTransform(block, yp, (char*)up, (char*)vp,
578                                            inw);
579                 else
580                         VidTransform_Rev(block, yp, (char*)up, (char*)vp, inw);
581 
582                 yp += 8;
583                 if (up) {
584                         up += 4;
585                         vp += 4;
586                 }
587                 *ts++ = now_;
588         }
589         return (data);
590 }
591 
592 void NvDecoder::recv(pktbuf* pb)
593 {
594         rtphdr* rh = (rtphdr*)pb->dp;
595         const nvhdr* ph = (nvhdr*)(rh + 1);
596         int h = ntohs(ph->height);
597         int w = ntohs(ph->width);
598         int color = w >> 15;
599         w &= 0xfff;
600         int fmt = h >> 12;
601         h &= 0xfff;
602         if (fmt == 0)
603                 use_dct_ = 0;
604         else if (fmt == 1)
605                 use_dct_ = 1;
606         else
607                 count(STAT_BAD_ENC);
608 #ifdef notyet
609         if (color != color_)
610                 /*FIXME should do this by invoking tcl command */
611                 setcolor(color);
612 #endif
613         if (w != inw_ || h != inh_) {
614                 if ((unsigned)w > 1000 || (unsigned)h > 1000) {
615                         /*FIXME*/
616                         w = 320;
617                         h = 240;
618                         count(STAT_BAD_GEOM);
619                 }
620                 resize(w, h);
621         }
622         const u_int8_t* end = &pb->dp[pb->len];
623         const u_int8_t* bp = (u_int8_t*)(ph + 1);
624         while (bp < end)
625                 bp = decode_run(bp, end, color);
626 
627         if (ntohs(rh->rh_flags) & RTP_M) {
628                 render_frame(frm_);
629                 resetndblk();
630         }
631         pb->release();
632 }
633 

~ [ 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.