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
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.