1 /*
2 * transcoder-nv.cc --
3 *
4 * Netvideo Transcoder
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/video/transcoder-nv.cc,v 1.7 2002/03/16 02:56:43 chema Exp $";
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <sys/param.h>
37 #include "config.h"
38 #include "inet.h"
39 #include "rtp.h"
40 #include "transcoder.h"
41 #include "transmitter.h"
42 #include "encoder.h"
43 #include "crdef.h"
44
45 #ifdef INFOPAD
46 #include "encoder-ipadvq.h"
47 #include "ipadchan.h"
48 #endif /* INFOPAD */
49
50 class NvTranscoder : public VideoTranscoder {
51 public:
52 NvTranscoder();
53 int recv(const rtphdr* rh, const u_char* bp, int cc, Transmitter& tx);
54 protected:
55 void process_hdr(const nvhdr*);
56 virtual void configure();
57 void info(char* wrk) const;
58 const u_char* decode_run(const u_char* data, const u_char* end,
59 int color, int mark);
60 void VidTransform_Rev(u_int* inp, u_char* yp, char* up, char* vp,
61 int width);
62 void NVDCT_RevTransform(u_int* inp, u_char *yp,
63 char* up, char* vp, int width);
64 int compute_margins(void);
65 struct margin {
66 int top;
67 int right;
68 int left;
69 } margin_;
70 int rcrop_;
71 int lcrop_;
72 int topcrop_;
73 int botcrop_;
74
75 int outw_;
76 int outh_;
77 int use_dct_;
78 u_char* frm_;
79 int color_;
80 };
81
82 static class NvTranscoderMatcher : public Matcher {
83 public:
84 NvTranscoderMatcher() : Matcher("transcoder") {}
85 TclObject* match(const char* id) {
86 if (strcmp(id, "nv") == 0)
87 return (new NvTranscoder());
88 return (0);
89 }
90 } nv_transcoder_matcher;
91
92 NvTranscoder::NvTranscoder()
93 :VideoTranscoder(sizeof(nvhdr)), use_dct_(0), frm_(0), color_(1)
94 {}
95
96 void NvTranscoder::configure()
97 {
98 if (compute_margins() != 0)
99 fprintf(stderr, "NvTranscoder: Couldn't compute margins.\n");
100 delete frm_;
101 int size = outw_ * outh_ * 2;
102 frm_ = new u_char[size];
103 memset(frm_, 0x80, size);
104 crinit(outw_, outh_);
105 }
106
107 int NvTranscoder::compute_margins()
108 {
109 /*
110 * Embed one image size in a bigger one.
111 * (extra areas will already be gray from init() )
112 */
113 margin& m = margin_;
114 m.top = m.left = m.right = 0;
115 lcrop_ = 0;
116 rcrop_ = inw_ >> 3;
117 topcrop_ = 0;
118 botcrop_ = inh_ >> 3;
119
120 int dx = outw_ - inw_;
121 int dy = outh_ - inh_;
122
123 /*
124 * If output size is smaller that intput, crop input image to fit
125 * output size, otherwise try and center the image in the larger
126 * frame, making sure to align on macroblock (16x16) boundaries.
127 */
128 if (dx < 0) {
129 dx = -dx;
130 /* Bail if can't align on block boundary. */
131 if (dx % 8 != 0)
132 return (-1);
133
134 int q = dx / 16;
135 if (q % 2 != 0)
136 /* Can't center crop horizontally */
137 lcrop_ = (dx - 16) / 2;
138 else
139 /* Center crop horizontally */
140 lcrop_ = dx / 2;
141
142 lcrop_ >>= 3;
143 rcrop_ -= lcrop_;
144 } else {
145 if (dx % 8 != 0)
146 return (-1);
147
148 /* Know dx is multiple of 8 at least */
149 if (dx % 16 == 8) {
150 /* crop one block and bias dx */
151 rcrop_--;
152 dx -= 8;
153 }
154
155 int q = dx / 16;
156 if (q % 2 != 0) {
157 /* Can't center horizontally */
158 m.right = ((dx - 16) / 2) >> 3;
159 m.left = ((dx + 16) / 2) >> 3;
160 } else
161 /* Center horizontally */
162 m.right = m.left = (dx / 2) >> 3;
163 }
164
165 if (dy < 0) {
166 dy = -dy;
167 /* Bail if can't align on block boundary. */
168 if (dy % 8 != 0)
169 return (-1);
170 int q = dy / 16;
171 if (q % 2 != 0)
172 /* Can't center crop vertically */
173 topcrop_ = (dy - 16) / 2;
174 else
175 /* Center crop vertically */
176 topcrop_ = dy / 2;
177 topcrop_ >>= 3;
178 botcrop_ -= topcrop_;
179 } else {
180 /* Bail if can't align on block boundary. */
181 if (dy % 8 != 0)
182 return (-1);
183
184 /* Know dy is multiple of 8 at least */
185 if (dy % 16 == 8) {
186 /* crop one block and bias dy */
187 botcrop_--;
188 dy -= 8;
189 }
190
191 int q = dy / 16;
192 if (q % 2 != 0)
193 /* Can't center vertically */
194 m.top = ((dy - 16) / 2) >> 3;
195 else
196 /* Center vertically */
197 m.top = (dy / 2) >> 3;
198 }
199 return (0);
200 }
201
202 void NvTranscoder::info(char* wrk) const
203 {
204 strcpy(wrk, use_dct_ ? "[dct]" : "[haar]");
205 }
206
207 /* Sick little macro which will limit x to [0..255] with logical ops */
208 #define UCLIMIT(x) ((t = (x)), (t &= ~(t>>31)), (t | ~((t-256) >> 31)))
209 /* A variant of above which will limit x to [-128..127] */
210 #define SCLIMIT(x) (UCLIMIT((x)+128)-128)
211
212 void NvTranscoder::VidTransform_Rev(u_int* inp, u_char *yp,
213 char* up, char* vp, int width)
214 {
215 register int i, t, t0, t1, t2, t3, t4, t5, *dataptr;
216 register int width2=2*width, width6=6*width;
217 register signed char *inpcptr=(signed char *)inp;
218 static int block[64];
219 #define SIGN_EXTEND(c) c
220
221 dataptr = block;
222 for (i=0; i<8; i++) {
223 if ((inp[0] << 8) == 0) {
224 t2 = t3 = t4 = t5 = SIGN_EXTEND(inpcptr[0]);
225 } else {
226 t4 = SIGN_EXTEND(inpcptr[0]);
227 t5 = SIGN_EXTEND(inpcptr[1]);
228 t0 = t4 - t5;
229 t1 = t4 + t5;
230
231 t4 = SIGN_EXTEND(inpcptr[2]);
232 t5 = SIGN_EXTEND(inpcptr[3]);
233 t2 = t0 - t4;
234 t3 = t0 + t4;
235 t4 = t1 - t5;
236 t5 = t1 + t5;
237 }
238
239 if (inp[1] == 0) {
240 dataptr[0] = dataptr[1] = t2;
241 dataptr[2] = dataptr[3] = t3;
242 dataptr[4] = dataptr[5] = t4;
243 dataptr[6] = dataptr[7] = t5;
244 } else {
245 t0 = SIGN_EXTEND(inpcptr[4]);
246 t1 = SIGN_EXTEND(inpcptr[5]);
247 dataptr[0] = t2 - t0;
248 dataptr[1] = t2 + t0;
249 dataptr[2] = t3 - t1;
250 dataptr[3] = t3 + t1;
251
252 t0 = SIGN_EXTEND(inpcptr[6]);
253 t1 = SIGN_EXTEND(inpcptr[7]);
254 dataptr[4] = t4 - t0;
255 dataptr[5] = t4 + t0;
256 dataptr[6] = t5 - t1;
257 dataptr[7] = t5 + t1;
258 }
259
260 inp += 2;
261 inpcptr += 8;
262 dataptr += 8;
263 }
264
265 dataptr = block;
266 for (i=0; i<8; i++) {
267 t4 = dataptr[0] + 128; /* Add back DC offset */
268 t5 = dataptr[8];
269 t0 = t4 - t5;
270 t1 = t4 + t5;
271
272 t4 = dataptr[16];
273 t5 = dataptr[24];
274 t2 = t0 - t4;
275 t3 = t0 + t4;
276 t4 = t1 - t5;
277 t5 = t1 + t5;
278
279 t0 = dataptr[32];
280 t1 = dataptr[40];
281 yp[0] = UCLIMIT(t2 - t0);
282 yp[width] = UCLIMIT(t2 + t0);
283 yp += width2;
284 yp[0] = UCLIMIT(t3 - t1);
285 yp[width] = UCLIMIT(t3 + t1);
286 yp += width2;
287
288 t0 = dataptr[48];
289 t1 = dataptr[56];
290 yp[0] = UCLIMIT(t4 - t0);
291 yp[width] = UCLIMIT(t4 + t0);
292 yp += width2;
293 yp[0] = UCLIMIT(t5 - t1);
294 yp[width] = UCLIMIT(t5 + t1);
295 yp -= width6;
296
297 yp++;
298 dataptr++;
299 }
300
301 if (up) {
302 int uswitch = 1;
303 signed char* p = (signed char*)up++;
304 dataptr = block;
305 for (i=0; i<8; i++) {
306 if ((inp[0] << 16) == 0) {
307 t2 = t3 = SIGN_EXTEND(inpcptr[0]);
308 t4 = t5 = SIGN_EXTEND(inpcptr[1]);
309 } else {
310 t0 = SIGN_EXTEND(inpcptr[0]);
311 t1 = SIGN_EXTEND(inpcptr[1]);
312
313 t4 = SIGN_EXTEND(inpcptr[2]);
314 t5 = SIGN_EXTEND(inpcptr[3]);
315 t2 = t0 - t4;
316 t3 = t0 + t4;
317 t4 = t1 - t5;
318 t5 = t1 + t5;
319 }
320
321 if (inp[1] == 0) {
322 dataptr[0] = dataptr[2] = t2;
323 dataptr[4] = dataptr[6] = t3;
324 dataptr[1] = dataptr[3] = t4;
325 dataptr[5] = dataptr[7] = t5;
326 } else {
327 t0 = SIGN_EXTEND(inpcptr[4]);
328 t1 = SIGN_EXTEND(inpcptr[5]);
329 dataptr[0] = t2 - t0;
330 dataptr[2] = t2 + t0;
331 dataptr[4] = t3 - t1;
332 dataptr[6] = t3 + t1;
333
334 t0 = SIGN_EXTEND(inpcptr[6]);
335 t1 = SIGN_EXTEND(inpcptr[7]);
336 dataptr[1] = t4 - t0;
337 dataptr[3] = t4 + t0;
338 dataptr[5] = t5 - t1;
339 dataptr[7] = t5 + t1;
340 }
341
342 inp += 2;
343 inpcptr += 8;
344 dataptr += 8;
345 }
346
347 dataptr = block;
348 for (i=0; i<8; i++) {
349 t4 = dataptr[0];
350 t5 = dataptr[8];
351 t0 = t4 - t5;
352 t1 = t4 + t5;
353
354 t4 = dataptr[16];
355 t5 = dataptr[24];
356 t2 = t0 - t4;
357 t3 = t0 + t4;
358 t4 = t1 - t5;
359 t5 = t1 + t5;
360
361 t0 = dataptr[32];
362 t1 = dataptr[40];
363
364 *p = SCLIMIT(t2 - t0) + 0x80;
365 p += width / 2;
366 *p = SCLIMIT(t2 + t0) + 0x80;
367 p += width / 2;
368 *p = SCLIMIT(t3 - t1) + 0x80;
369 p += width / 2;
370 *p = SCLIMIT(t3 + t1) + 0x80;
371 p += width / 2;
372
373 t0 = dataptr[48];
374 t1 = dataptr[56];
375 *p = SCLIMIT(t4 - t0) + 0x80;
376 p += width / 2;
377 *p = SCLIMIT(t4 + t0) + 0x80;
378 p += width / 2;
379 *p = SCLIMIT(t5 - t1) + 0x80;
380 p += width / 2;
381 *p = SCLIMIT(t5 + t1) + 0x80;
382 p += width / 2;
383
384 if (uswitch) {
385 uswitch = 0;
386 p = (signed char*)vp++;
387 } else {
388 uswitch = 1;
389 p = (signed char*)up++;
390 }
391 dataptr++;
392 }
393 }
394 }
395
396 void NvTranscoder::NVDCT_RevTransform(u_int* inp, u_char *yp,
397 char* up, char* vp, int width)
398 {
399 int i, t, *dataptr;
400 int a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3;
401 int8_t *inpcptr=(int8_t *)inp;
402 static int block[64];
403
404 dataptr = block;
405 for (i=0; i<8; i++) {
406 if ((inp[0]|inp[1]) == 0) {
407 dataptr[0] = dataptr[1] = dataptr[2] = dataptr[3] =
408 dataptr[4] = dataptr[5] = dataptr[6] = dataptr[7] = 0;
409 } else {
410 b0 = inpcptr[0] << 4;
411 b1 = inpcptr[4] << 4;
412 b2 = inpcptr[2] << 4;
413 b3 = inpcptr[6] << 4;
414
415 a0 = (362 * (b0+b1)) >> 9;
416 a1 = (362 * (b0-b1)) >> 9;
417 a2 = (196*b2 - 473*b3) >> 9;
418 a3 = (473*b2 + 196*b3) >> 9;
419
420 b0 = a0+a3;
421 b1 = a1+a2;
422 b2 = a1-a2;
423 b3 = a0-a3;
424
425 a0 = inpcptr[1] << 4;
426 a1 = inpcptr[3] << 4;
427 a2 = inpcptr[5] << 4;
428 a3 = inpcptr[7] << 4;
429
430 c0 = (100*a0 - 502*a3) >> 9;
431 c1 = (426*a2 - 284*a1) >> 9;
432 c2 = (426*a1 + 284*a2) >> 9;
433 c3 = (502*a0 + 100*a3) >> 9;
434
435 a0 = c0+c1;
436 a1 = c0-c1;
437 a2 = c3-c2;
438 a3 = c3+c2;
439
440 c0 = a0;
441 c1 = (362 * (a2-a1)) >> 9;
442 c2 = (362 * (a1+a2)) >> 9;
443 c3 = a3;
444
445 dataptr[0] = b0+c3;
446 dataptr[1] = b1+c2;
447 dataptr[2] = b2+c1;
448 dataptr[3] = b3+c0;
449 dataptr[4] = b3-c0;
450 dataptr[5] = b2-c1;
451 dataptr[6] = b1-c2;
452 dataptr[7] = b0-c3;
453 }
454
455 inp += 2;
456 inpcptr += 8;
457 dataptr += 8;
458 }
459
460 dataptr = block;
461 for (i=0; i<8; i++) {
462 b0 = dataptr[0]+1448; /* Add back DC offset */
463 b1 = dataptr[32];
464 b2 = dataptr[16];
465 b3 = dataptr[48];
466
467 a0 = (362 * (b0+b1)) >> 9;
468 a1 = (362 * (b0-b1)) >> 9;
469 a2 = (196*b2 - 473*b3) >> 9;
470 a3 = (473*b2 + 196*b3) >> 9;
471
472 b0 = a0+a3;
473 b1 = a1+a2;
474 b2 = a1-a2;
475 b3 = a0-a3;
476
477 a0 = dataptr[8];
478 a1 = dataptr[24];
479 a2 = dataptr[40];
480 a3 = dataptr[56];
481
482 c0 = (100*a0 - 502*a3) >> 9;
483 c1 = (426*a2 - 284*a1) >> 9;
484 c2 = (426*a1 + 284*a2) >> 9;
485 c3 = (502*a0 + 100*a3) >> 9;
486
487 a0 = c0+c1;
488 a1 = c0-c1;
489 a2 = c3-c2;
490 a3 = c3+c2;
491
492 c0 = a0;
493 c1 = (362 * (a2-a1)) >> 9;
494 c2 = (362 * (a2+a1)) >> 9;
495 c3 = a3;
496
497 yp[0] = UCLIMIT((b0+c3+4) >> 3);
498 yp[width] = UCLIMIT((b1+c2+4) >> 3);
499 yp += 2*width;
500
501 yp[0] = UCLIMIT((b2+c1+4) >> 3);
502 yp[width] = UCLIMIT((b3+c0+4) >> 3);
503 yp += 2*width;
504
505 yp[0] = UCLIMIT((b3-c0+4) >> 3);
506 yp[width] = UCLIMIT((b2-c1+4) >> 3);
507 yp += 2*width;
508
509 yp[0] = UCLIMIT((b1-c2+4) >> 3);
510 yp[width] = UCLIMIT((b0-c3+4) >> 3);
511 yp -= 6*width;
512
513 yp++;
514 dataptr++;
515 }
516
517 if (up) {
518 u_int8_t uvblk[64];
519 u_int8_t* uvp = uvblk;
520 #define width 8
521 dataptr = block;
522 for (i=0; i<8; i++) {
523 if ((inp[0]|inp[1]) == 0) {
524 dataptr[0] = dataptr[1] = dataptr[2] = dataptr[3] =
525 dataptr[4] = dataptr[5] = dataptr[6] = dataptr[7] = 0;
526 } else {
527 b0 = inpcptr[0] << 4;
528 b2 = inpcptr[2] << 4;
529 b1 = inpcptr[4] << 4;
530 b3 = inpcptr[6] << 4;
531
532 a0 = (362 * (b0+b1)) >> 9;
533 a1 = (362 * (b0-b1)) >> 9;
534 a2 = (196*b2 - 473*b3) >> 9;
535 a3 = (473*b2 + 196*b3) >> 9;
536
537 dataptr[0] = a0+a3;
538 dataptr[2] = a1+a2;
539 dataptr[4] = a1-a2;
540 dataptr[6] = a0-a3;
541
542 b0 = inpcptr[1] << 4;
543 b2 = inpcptr[3] << 4;
544 b1 = inpcptr[5] << 4;
545 b3 = inpcptr[7] << 4;
546
547 a0 = (362 * (b0+b1)) >> 9;
548 a1 = (362 * (b0-b1)) >> 9;
549 a2 = (196*b2 - 473*b3) >> 9;
550 a3 = (473*b2 + 196*b3) >> 9;
551
552 dataptr[1] = a0+a3;
553 dataptr[3] = a1+a2;
554 dataptr[5] = a1-a2;
555 dataptr[7] = a0-a3;
556 }
557
558 inp += 2;
559 inpcptr += 8;
560 dataptr += 8;
561 }
562
563 dataptr = block;
564 for (i=0; i<8; i++) {
565 b0 = dataptr[0];
566 b1 = dataptr[32];
567 b2 = dataptr[16];
568 b3 = dataptr[48];
569
570 a0 = (362 * (b0+b1)) >> 9;
571 a1 = (362 * (b0-b1)) >> 9;
572 a2 = (196*b2 - 473*b3) >> 9;
573 a3 = (473*b2 + 196*b3) >> 9;
574
575 b0 = a0+a3;
576 b1 = a1+a2;
577 b2 = a1-a2;
578 b3 = a0-a3;
579
580 a0 = dataptr[8];
581 a1 = dataptr[24];
582 a2 = dataptr[40];
583 a3 = dataptr[56];
584
585 c0 = (100*a0 - 502*a3) >> 9;
586 c1 = (426*a2 - 284*a1) >> 9;
587 c2 = (426*a1 + 284*a2) >> 9;
588 c3 = (502*a0 + 100*a3) >> 9;
589
590 a0 = c0+c1;
591 a1 = c0-c1;
592 a2 = c3-c2;
593 a3 = c3+c2;
594
595 c0 = a0;
596 c1 = (362 * (a2-a1)) >> 9;
597 c2 = (362 * (a2+a1)) >> 9;
598 c3 = a3;
599
600 uvp[0] = SCLIMIT((b0+c3+4) >> 3);
601 uvp[width] = SCLIMIT((b1+c2+4) >> 3);
602 uvp += 2*width;
603
604 uvp[0] = SCLIMIT((b2+c1+4) >> 3);
605 uvp[width] = SCLIMIT((b3+c0+4) >> 3);
606 uvp += 2*width;
607
608 uvp[0] = SCLIMIT((b3-c0+4) >> 3);
609 uvp[width] = SCLIMIT((b2-c1+4) >> 3);
610 uvp += 2*width;
611
612 uvp[0] = SCLIMIT((b1-c2+4) >> 3);
613 uvp[width] = SCLIMIT((b0-c3+4) >> 3);
614 uvp -= 6*width;
615
616 uvp++;
617 dataptr++;
618 }
619 #undef width
620 uvp = uvblk;
621 for (i = 0; i < 8; ++i) {
622 up[0] = uvp[0] + 0x80;
623 vp[0] = uvp[1] + 0x80;
624 up[1] = uvp[2] + 0x80;
625 vp[1] = uvp[3] + 0x80;
626 up[2] = uvp[4] + 0x80;
627 vp[2] = uvp[5] + 0x80;
628 up[3] = uvp[6] + 0x80;
629 vp[3] = uvp[7] + 0x80;
630 up += width >> 1;
631 vp += width >> 1;
632 uvp += 8;
633 }
634 }
635 }
636
637 #define VIDCODE_COLORFLAG 0x8000
638 #define VIDCODE_WIDTHMASK 0x0fff
639
640 const u_char* NvTranscoder::decode_run(const u_char* data, const u_char* end,
641 int color, int mark)
642 {
643 if (end - data < 3)
644 return (end);
645
646 int w0, w;
647 w0 = w = *data++;
648 int x0 = *data++;
649 int y0 = *data++;
650
651 margin& m = margin_;
652 if ((x0+w > inw_/8) || (y0 >= inh_/8))
653 return (end);
654
655 /* Remember original coords */
656 int y = y0;
657 int x = x0;
658
659 /* Skip margins */
660 y0 += m.top;
661 x0 += m.left;
662
663 /* Adjust for crops */
664 y0 -= topcrop_;
665 x0 -= lcrop_;
666
667 int offset = y0 * outw_;
668 #ifdef notdef
669 u_char* ts = &rvts_[(offset >> 3) + x0];
670 #endif
671 u_char* crv = &crvec_[(offset >> 3) + x0];
672
673 offset = (offset << 3) + (x0 << 3);
674 u_char* yp = &frm_[offset];
675 int s = outw_ * outh_;/* FIXME */
676 u_char* up = frm_ + s + (offset >> 1);
677 u_char* vp = up + (s >> 1);
678 while (w-- > 0) {
679 if (data >= end) {
680 return (end);
681 }
682 static u_int block[32];
683 int lim=color? 128 : 64;
684 for (int i=0; i<lim; ) {
685 int run = *data++;
686 int j = run >> 6;
687 int k = run & 0x3f;
688 if (i+j+k > lim) {
689 return (end);
690 }
691 char* blkp = (char*)block;
692 while (j--) blkp[i++] = (char) *data++;
693 while (k--) blkp[i++] = 0;
694 }
695 if (y >= topcrop_ && y < botcrop_ && x >= lcrop_ &&
696 x < rcrop_) {
697 if (use_dct_)
698 NVDCT_RevTransform(block, yp, (char*)up,
699 (char*)vp, outw_);
700 else
701 VidTransform_Rev(block, yp, (char*)up,
702 (char*)vp, outw_);
703 *crv = mark;
704 }
705
706 crv += 1;
707 yp += 8;
708 x++;
709 if (up) {
710 up += 4;
711 vp += 4;
712 }
713 #ifdef notdef
714 *ts++ = now_;
715 #endif
716 }
717 return (data);
718 }
719
720 void NvTranscoder::process_hdr(const nvhdr* ph)
721 {
722 int reconfig = 0;
723
724 int h = ntohs(ph->height);
725 int w = ntohs(ph->width);
726 color_ = w >> 15;
727 w &= 0xfff;
728 int fmt = h >> 12;
729 h &= 0xfff;
730 if (fmt == 0)
731 use_dct_ = 0;
732 else if (fmt == 1)
733 use_dct_ = 1;
734 #ifdef notyet
735 if (color != color_)
736 /*FIXME should do this by invoking tcl command */
737 setcolor(color);
738 #endif
739 if (w != inw_ || h != inh_) {
740 if ((unsigned)w > 1000 || (unsigned)h > 1000) {
741 /*FIXME*/
742 w = 320;
743 h = 240;
744 }
745 inw_ = w;
746 inh_ = h;
747 encoder_->framesize(inw_, inh_, outw_, outh_);
748 reconfig = 1;
749 }
750 if (reconfig)
751 configure();
752
753 }
754
755 int NvTranscoder::recv(const rtphdr* rh, const u_char* bp, int cc,
756 Transmitter& tx)
757 {
758 const nvhdr* ph = (nvhdr*)(rh + 1);
759 process_hdr(ph);
760
761 bp += sizeof(nvhdr);
762 cc -= sizeof(nvhdr);
763 const u_char* end = bp + cc;
764 while (bp < end)
765 bp = decode_run(bp, end, color_, CR_SEND|CR_MOTION);
766
767 if (!(ntohs(rh->rh_flags) & RTP_M))
768 return (0);
769 /*
770 * Have a frame.
771 */
772 if (tx.bps() == 0)
773 return (1);
774
775 double now = gettimeofday();
776 if (fc_ <= now) {
777 /* If we have fallen behind (>200ms), re-sync. */
778 if (now - fc_ > 200000.)
779 fc_ = now;
780 VideoFrame vf(ntohl(rh->rh_ts), frm_, outw_, outh_, 0, 422);
781 int ecc = encoder_->consume(&vf, tx);
782 age_blocks();
783 double bits = 8 * double(ecc);
784 fc_ += 1e6 * bits / tx.bps();
785 }
786 return (1);
787 }
788
789 #ifdef INFOPAD
790 void NvIpadVQTranscoder::configure(const u_char* p, Network* n)
791 {
792 NvTranscoder::configure(p, n);
793
794 IpadChannel* c = (IpadChannel*)n;
795 encoder_ = new IpadVQEncoder(c, outw_, outh_, 422, 0);
796 }
797
798 void NvIpadVQTranscoder::resize(int w, int h)
799 {
800 outw_ = inw_ = w;
801 outh_ = inh_ = h;
802 /* FIXME */
803 u_int bps = encoder_->bps();
804 delete encoder_;
805 encoder_ = new IpadVQEncoder((IpadChannel*)net_, outw_, outh_, 422, 0);
806 encoder_->bps(bps);
807 }
808
809 int NvIpadVQTranscoder::recv(const rtphdr* rh, const u_char* bp, int cc, int)
810 {
811 const nvhdr* ph = (nvhdr*)(rh + 1);
812 int reconfig = process_hdr(ph);
813 if (reconfig)
814 reconfigure();
815
816 bp += sizeof(nvhdr);
817 cc -= sizeof(nvhdr);
818 const u_char* end = bp + cc;
819 while (bp < end)
820 bp = decode_run(bp, end, color_, CR_SEND|CR_MOTION);
821
822 if (!(ntohs(rh->rh_flags) & RTP_M))
823 return (0);
824 /*
825 * Have a frame.
826 */
827 if (bps() == 0)
828 return (1);
829 double now = gettimeofday();
830 if (fc_ <= now) {
831 /* If we have fallen behind (>200ms), re-sync. */
832 if (now - fc_ > 200000.)
833 fc_ = now;
834 int ecc = encoder()->encode(frm_, outw_, outh_, 0);
835 age_blocks();
836 double bits = 8 * double(ecc);
837 obits_ += int(bits);
838 ofrms_ += 1;
839 opkts_ = encoder()->np();
840 fc_ += 1e6 * bits / double(bps());
841 }
842 return (1);
843 }
844 #endif /* INFOPAD */
845
846
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.