1 /*
2 * encoder-nv.cc --
3 *
4 * Netvideo encoder
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 encode 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/encoder-nv.cc,v 1.12 2003/11/19 19:20:17 aswan Exp $";
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <errno.h>
38 #include "rtp/inet.h"
39 #include "rtp/rtp.h"
40 #include "tclcl.h"
41 #include "codec/crdef.h"
42
43 /*FIXME*/
44 #define MAXBLOCK (128+32)
45
46 #include <sys/types.h>
47 #ifndef WIN32
48 #include <netinet/in.h>
49 #endif
50 #include "rtp/pktbuf-rtp.h"
51 #include "codec/module.h"
52
53 class NvEncoder : public EncoderModule {
54 public:
55 NvEncoder();
56 ~NvEncoder();
57 virtual int command(int argc, const char*const* argv);
58 virtual void recv(Buffer*);
59 protected:
60 void size(int w, int h);
61 int flush(pktbuf*, int sync);
62 void putblock(const u_char* yp, const u_char* up, const u_char* vp,
63 int x, int y, int loss, u_char*& runlen);
64 int endblock();
65 void VidTransform_Fwd(const u_char* yp,
66 const u_char* up,
67 const u_char* vp,
68 int width, u_int32_t* out) const;
69 void NVDCT_FwdTransform(const u_int8_t *yp,
70 const u_int8_t *up,
71 const u_int8_t* vp,
72 int width, u_int32_t *out) const;
73
74 int nw_;
75 int nh_;
76 int loss_;
77 int use_dct_;
78
79 u_char* pt_;
80 u_char* ep_;
81 };
82
83
84 static class NvEncoderClass : public TclClass {
85 public:
86 NvEncoderClass() : TclClass("Module/VideoEncoder/Pixel/NV") {}
87 TclObject* create(int /* argc */, const char*const* /* argv */) {
88 return (new NvEncoder);
89 }
90 } encoder_matcher_nv;
91
92 NvEncoder::NvEncoder() :
93 nw_(0), nh_(0), loss_(2), use_dct_(0), pt_(0), ep_(0)
94 {
95 width_ = 0;
96 height_ = 0;
97 }
98
99 NvEncoder::~NvEncoder()
100 {
101 }
102
103 #define HLEN (sizeof(rtphdr) + sizeof(nvhdr))
104
105 int NvEncoder::flush(pktbuf* pb, int sync)
106 {
107 int cc = pt_ - (u_char*)&pb->data[HLEN];
108 /*
109 * If there's no packet data to send and we don't need
110 * to transmit a sync bit (to indicate a new frame),
111 * then release the packet buffer and return.
112 */
113 if (cc == 0 && !sync) {
114 pool_->release(pb);
115 return (0);
116 }
117 pb->len = cc + HLEN;
118 rtphdr* rh = (rtphdr*)pb->data;
119 if (sync)
120 rh->rh_flags |= htons(RTP_M);
121
122 nvhdr* nh = (nvhdr*)(rh + 1);
123 nh->width = nw_;
124 nh->height = nh_ | use_dct_;
125
126 target_->recv(pb);
127
128 return (cc);
129 }
130
131 void NvEncoder::size(int w, int h)
132 {
133 FrameModule::size(w, h);
134 nw_ = htons(w | 0x8000);
135 nh_ = htons(h);
136 }
137
138 int NvEncoder::command(int argc, const char*const* argv)
139 {
140 if (argc == 3) {
141 if (strcmp(argv[1], "q") == 0) {
142 loss_ = atoi(argv[2]);
143 return (TCL_OK);
144 }
145 if (strcmp(argv[1], "use-dct") == 0) {
146 use_dct_ = atoi(argv[2]) ? htons(1 << 12) : 0;
147 return (TCL_OK);
148 }
149 }
150 return (EncoderModule::command(argc, argv));
151 }
152
153 void NvEncoder::putblock(const u_char* yp, const u_char* up, const u_char* vp,
154 int x, int y, int loss, u_char*& runlen)
155 {
156 if (runlen == 0) {
157 runlen = pt_;
158 *pt_++ = 1;
159 *pt_++ = x;
160 *pt_++ = y;
161 } else
162 ++*runlen;
163
164 static u_int32_t block[32];
165 if (use_dct_)
166 NVDCT_FwdTransform(yp, up, vp, width_, block);
167 else
168 VidTransform_Fwd(yp, up, vp, width_, block);
169
170 if (loss > 0) {
171 signed char *blkp = (signed char*)block;
172 if ((blkp[2]>=-loss) && (blkp[2]<=loss)) blkp[2] = 0;
173 if ((blkp[3]>=-loss) && (blkp[3]<=loss)) blkp[3] = 0;
174 if ((blkp[4]>=-loss) && (blkp[5]<=loss)) blkp[4] = 0;
175 if ((blkp[5]>=-loss) && (blkp[5]<=loss)) blkp[5] = 0;
176 if ((blkp[6]>=-loss) && (blkp[6]<=loss)) blkp[6] = 0;
177 if ((blkp[7]>=-loss) && (blkp[7]<=loss)) blkp[7] = 0;
178 blkp = ((signed char *)block)+10;
179 int i;
180 for (i=10; i<64; i+=6, blkp+=6) {
181 if ((blkp[0]>=-loss) && (blkp[0]<=loss)) blkp[0] = 0;
182 if ((blkp[1]>=-loss) && (blkp[1]<=loss)) blkp[1] = 0;
183 if ((blkp[2]>=-loss) && (blkp[2]<=loss)) blkp[2] = 0;
184 if ((blkp[3]>=-loss) && (blkp[3]<=loss)) blkp[3] = 0;
185 if ((blkp[4]>=-loss) && (blkp[4]<=loss)) blkp[4] = 0;
186 if ((blkp[5]>=-loss) && (blkp[5]<=loss)) blkp[5] = 0;
187 }
188
189 if (up != 0) {
190 blkp = ((signed char *)block)+64;
191 if ((blkp[2]>=-2*loss) && (blkp[2]<=2*loss))
192 blkp[2] = 0;
193 if ((blkp[3]>=-2*loss) && (blkp[3]<=2*loss))
194 blkp[3] = 0;
195 if ((blkp[4]>=-2*loss) && (blkp[5]<=2*loss))
196 blkp[4] = 0;
197 if ((blkp[5]>=-2*loss) && (blkp[5]<=2*loss))
198 blkp[5] = 0;
199 if ((blkp[6]>=-2*loss) && (blkp[6]<=2*loss))
200 blkp[6] = 0;
201 if ((blkp[7]>=-2*loss) && (blkp[7]<=2*loss))
202 blkp[7] = 0;
203 blkp = ((signed char *)block)+74;
204 for (i=10; i<64; i+=6, blkp+=6) {
205 if ((blkp[0]>=-2*loss) && (blkp[0]<=2*loss))
206 blkp[0] = 0;
207 if ((blkp[1]>=-2*loss) && (blkp[1]<=2*loss))
208 blkp[1] = 0;
209 if ((blkp[2]>=-2*loss) && (blkp[2]<=2*loss))
210 blkp[2] = 0;
211 if ((blkp[3]>=-2*loss) && (blkp[3]<=2*loss))
212 blkp[3] = 0;
213 if ((blkp[4]>=-2*loss) && (blkp[4]<=2*loss))
214 blkp[4] = 0;
215 if ((blkp[5]>=-2*loss) && (blkp[5]<=2*loss))
216 blkp[5] = 0;
217 }
218 }
219 }
220
221 /* FIXME: The ntohl() calls here need to be redone as something more
222 efficient for little-endian machines! */
223 u_int32_t* blkwp = block;
224 u_int32_t* blkwLim = up? block+32 : block+16;
225 int i = 2;
226 int zcount = 0;
227 u_int32_t blkw = ntohl(*blkwp++);
228 pt_[1] = blkw >> 24;
229 blkw <<= 8;
230 int rem = 3;
231 do {
232 int b;
233 while ((b = blkw >> 24) != 0) {
234 pt_[i++] = b;
235 blkw <<= 8;
236 rem--;
237 if (i == 4) break;
238 if (rem == 0) {
239 if (blkwp == blkwLim) break;
240 blkw = ntohl(*blkwp++);
241 rem = 4;
242 }
243 }
244
245 while (1) {
246 if (zcount+rem >= 63) {
247 break;
248 } else if (blkw == 0) {
249 zcount += rem;
250 rem = 0;
251 if (blkwp == blkwLim) break;
252 blkw = ntohl(*blkwp++);
253 rem = 4;
254 } else if ((blkw >> 24) == 0) {
255 zcount++;
256 blkw <<= 8;
257 rem--;
258 } else break;
259 }
260
261 *pt_ = ((i-1) << 6) + zcount;
262 pt_ += i;
263 if (pt_ > ep_)
264 abort();
265 i = 1;
266 zcount = 0;
267 } while ((rem != 0) || (blkwp != blkwLim));
268 }
269
270 void NvEncoder::recv(Buffer* bp)
271 {
272 const VideoFrame* vf = (VideoFrame*)bp;
273 if (!samesize(vf))
274 size(vf->width_, vf->height_);
275 YuvFrame* p = (YuvFrame*)vf;
276
277 pktbuf* pb = pool_->alloc(p->ts_, RTP_PT_NV);
278 pt_ = &pb->data[HLEN];
279 ep_ = pt_ + mtu_ - HLEN;
280
281 int cc = 0;
282 u_char* runlen;
283 int stride = 7 * width_;
284 int off = framesize_;
285 const u_char* lum = p->bp_;
286 const u_char* chm = lum + off;
287 off >>= 1;
288 int w = width_ >> 3;
289 int h = height_ >> 3;
290 const u_int8_t* crvec = p->crvec_;
291 for (int y = 0; y < h; ++y) {
292 runlen = 0;
293 for (int x = 0; x < w; ++x) {
294 if (pt_ + MAXBLOCK >= ep_) {
295 cc += flush(pb, 0);
296 runlen = 0;
297 pb = pool_->alloc(p->ts_, RTP_PT_NV);
298 pt_ = &pb->data[HLEN];
299 ep_ = pt_ + mtu_ - HLEN;
300 }
301 int cr = *crvec;
302 if (cr & CR_SEND) {
303 cr = CR_QUALITY(cr);
304 int loss;
305 if (cr == CR_HQ)
306 loss = 0;
307 else
308 loss = loss_;
309
310 putblock(lum, chm, chm + off,
311 x, y, loss, runlen);
312 } else
313 /*
314 * We're going to skip a block.
315 * Invalidate the run.
316 */
317 runlen = 0;
318
319 if (x & 1)
320 ++crvec;
321
322 lum += 8;
323 chm += 4;
324 }
325 if ((y & 1) == 0)
326 crvec -= width_ / 16;
327
328 lum += stride;
329 chm += stride >> 1;
330 }
331 cc += flush(pb, 1);
332 nb_ += cc;
333 }
334
335 /*
336 * Haar transform the block, the way nv expects it
337 * (i.e., interleaved u,v)
338 */
339 void NvEncoder::VidTransform_Fwd(const u_char *yp,
340 const u_char *up,
341 const u_char* vp,
342 int stride, u_int32_t *out) const
343 {
344 register int i, t0, t1, t2, t3, t4, t5, *dataptr;
345 register int stride2=2*stride, stride6=6*stride;
346 register char *outcptr = (char *)out;
347 static int block[64];
348
349 dataptr = block;
350 for (i=0; i<8; i++) {
351 t0 = yp[0];
352 t1 = yp[stride];
353 t2 = t0 + t1;
354 dataptr[32] = (t1 - t0) << 2;
355 yp += stride2;
356
357 t0 = yp[0];
358 t1 = yp[stride];
359 t3 = t0 + t1;
360 dataptr[40] = (t1 - t0) << 2;
361 yp += stride2;
362
363 t0 = yp[0];
364 t1 = yp[stride];
365 t4 = t0 + t1;
366 dataptr[48] = (t1 - t0) << 2;
367 yp += stride2;
368
369 t0 = yp[0];
370 t1 = yp[stride];
371 t5 = t0 + t1;
372 dataptr[56] = (t1 - t0) << 2;
373 yp -= stride6;
374
375 t0 = t2 + t3;
376 t1 = t4 + t5;
377 dataptr[0] = t0 + t1 - 1024; /* Correct for DC offset */
378 dataptr[8] = t1 - t0;
379 dataptr[16] = (t3 - t2) << 1;
380 dataptr[24] = (t5 - t4) << 1;
381
382 yp++;
383 dataptr++;
384 }
385
386 dataptr = block;
387 for (i=0; i<8; i++) {
388 t0 = dataptr[0];
389 t1 = dataptr[1];
390 t2 = t0 + t1;
391 outcptr[4] = (t1 - t0 + 7) >> 4;
392
393 t0 = dataptr[2];
394 t1 = dataptr[3];
395 t3 = t0 + t1;
396 outcptr[5] = (t1 - t0 + 7) >> 4;
397
398 t0 = dataptr[4];
399 t1 = dataptr[5];
400 t4 = t0 + t1;
401 outcptr[6] = (t1 - t0 + 7) >> 4;
402
403 t0 = dataptr[6];
404 t1 = dataptr[7];
405 t5 = t0 + t1;
406 outcptr[7] = (t1 - t0 + 7) >> 4;
407
408 t0 = t2 + t3;
409 t1 = t4 + t5;
410 outcptr[0] = (t0 + t1 + 31) >> 6;
411 outcptr[1] = (t1 - t0 + 31) >> 6;
412 outcptr[2] = (t3 - t2 + 15) >> 5;
413 outcptr[3] = (t5 - t4 + 15) >> 5;
414
415 dataptr += 8;
416 outcptr += 8;
417 }
418
419 if (up != 0) {
420 stride >>= 1;
421 stride2 >>= 1;
422 stride6 >>= 1;
423
424 int uswitch = 1;
425 const u_char* p = up++;
426 dataptr = block;
427 for (i=0; i<8; i++) {
428 t0 = p[0] - 0x80;
429 t1 = p[stride] - 0x80;
430 t2 = t0 + t1;
431 dataptr[32] = (t1 - t0) << 2;
432 p += stride2;
433
434 t0 = p[0] - 0x80;
435 t1 = p[stride] - 0x80;
436 t3 = t0 + t1;
437 dataptr[40] = (t1 - t0) << 2;
438 p += stride2;
439
440 t0 = p[0] - 0x80;
441 t1 = p[stride] - 0x80;
442 t4 = t0 + t1;
443 dataptr[48] = (t1 - t0) << 2;
444
445 t0 = p[0] - 0x80;
446 t1 = p[stride] - 0x80;
447 t5 = t0 + t1;
448 dataptr[56] = (t1 - t0) << 2;
449 p -= stride6;
450
451 t0 = t2 + t3;
452 t1 = t4 + t5;
453 dataptr[0] = t0 + t1;
454 dataptr[8] = t1 - t0;
455 dataptr[16] = (t3 - t2) << 1;
456 dataptr[24] = (t5 - t4) << 1;
457
458 if (uswitch) {
459 uswitch = 0;
460 p = vp++;
461 } else {
462 uswitch = 1;
463 p = up++;
464 }
465 dataptr++;
466 }
467
468 dataptr = block;
469 for (i=0; i<8; i++) {
470 t0 = dataptr[0];
471 t1 = dataptr[2];
472 t2 = t0 + t1;
473 outcptr[4] = (t1 - t0 + 7) >> 4;
474
475 t0 = dataptr[4];
476 t1 = dataptr[6];
477 t3 = t0 + t1;
478 outcptr[5] = (t1 - t0 + 7) >> 4;
479
480 t0 = dataptr[1];
481 t1 = dataptr[3];
482 t4 = t0 + t1;
483 outcptr[6] = (t1 - t0 + 7) >> 4;
484
485 t0 = dataptr[5];
486 t1 = dataptr[7];
487 t5 = t0 + t1;
488 outcptr[7] = (t1 - t0 + 7) >> 4;
489
490 outcptr[0] = (t2 + t3 + 15) >> 5;
491 outcptr[1] = (t4 + t5 + 15) >> 5;
492 outcptr[2] = (t3 - t2 + 15) >> 5;
493 outcptr[3] = (t5 - t4 + 15) >> 5;
494
495 dataptr += 8;
496 outcptr += 8;
497 }
498 }
499 }
500
501 void NvEncoder::NVDCT_FwdTransform(const u_int8_t *yp,
502 const u_int8_t *up,
503 const u_int8_t* vp,
504 int width, u_int32_t *out) const
505 {
506 int i, t0, t1, *dataptr;
507 int a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3;
508 int8_t *outcptr=(int8_t *)out;
509 static int block[64];
510
511 dataptr = block;
512 for (i=0; i<8; i++) {
513 t0 = yp[0];
514 t1 = yp[7*width];
515 a0 = t0+t1;
516 c3 = t0-t1;
517 yp += width;
518
519 t0 = yp[0];
520 t1 = yp[5*width];
521 a1 = t0+t1;
522 c2 = t0-t1;
523 yp += width;
524
525 t0 = yp[0];
526 t1 = yp[3*width];
527 a2 = t0+t1;
528 c1 = t0-t1;
529 yp += width;
530
531 t0 = yp[0];
532 t1 = yp[width];
533 a3 = t0+t1;
534 c0 = t0-t1;
535 yp -= 3*width;
536
537 b0 = a0+a3;
538 b1 = a1+a2;
539 b2 = a1-a2;
540 b3 = a0-a3;
541
542 dataptr[0] = (362 * (b0+b1-1024)) >> 7; /* Correct for DC offset */
543 dataptr[32] = (362 * (b0-b1)) >> 7;
544 dataptr[16] = (196*b2 + 473*b3) >> 7;
545 dataptr[48] = (196*b3 - 473*b2) >> 7;
546
547 b0 = (362 * (c2-c1)) >> 7;
548 b1 = (362 * (c2+c1)) >> 7;
549 c0 = c0 << 2;
550 c3 = c3 << 2;
551
552 a0 = c0+b0;
553 a1 = c0-b0;
554 a2 = c3-b1;
555 a3 = c3+b1;
556
557 dataptr[8] = (100*a0 + 502*a3) >> 9;
558 dataptr[24] = (426*a2 - 284*a1) >> 9;
559 dataptr[40] = (426*a1 + 284*a2) >> 9;
560 dataptr[56] = (100*a3 - 502*a0) >> 9;
561
562 yp++;
563 dataptr++;
564 }
565
566 dataptr = block;
567 for (i=0; i<8; i++) {
568 t0 = dataptr[0];
569 t1 = dataptr[7];
570 a0 = t0+t1;
571 c3 = t0-t1;
572
573 t0 = dataptr[1];
574 t1 = dataptr[6];
575 a1 = t0+t1;
576 c2 = t0-t1;
577
578 t0 = dataptr[2];
579 t1 = dataptr[5];
580 a2 = t0+t1;
581 c1 = t0-t1;
582
583 t0 = dataptr[3];
584 t1 = dataptr[4];
585 a3 = t0+t1;
586 c0 = t0-t1;
587
588 b0 = a0+a3;
589 b1 = a1+a2;
590 b2 = a1-a2;
591 b3 = a0-a3;
592
593 outcptr[0] = (362 * (b0+b1) + 32768) >> 16;
594 outcptr[4] = (362 * (b0-b1) + 32768) >> 16;
595 outcptr[2] = (196*b2 + 473*b3 + 32768) >> 16;
596 outcptr[6] = (196*b3 - 473*b2 + 32768) >> 16;
597
598 b0 = (362 * (c2-c1)) >> 9;
599 b1 = (362 * (c2+c1)) >> 9;
600
601 a0 = c0+b0;
602 a1 = c0-b0;
603 a2 = c3-b1;
604 a3 = c3+b1;
605
606 outcptr[1] = (100*a0 + 502*a3 + 32768) >> 16;
607 outcptr[3] = (426*a2 - 284*a1 + 32768) >> 16;
608 outcptr[5] = (426*a1 + 284*a2 + 32768) >> 16;
609 outcptr[7] = (100*a3 - 502*a0 + 32768) >> 16;
610
611 dataptr += 8;
612 outcptr += 8;
613 }
614
615 if (up) {
616 int8_t uvblk[64];
617
618 /* FIXME interleave how nv wants it */
619 int8_t* uvp = uvblk;
620 for (i = 0; i < 8; ++i) {
621 uvp[0] = up[0] + 0x80;
622 uvp[1] = vp[0] + 0x80;
623 uvp[2] = up[1] + 0x80;
624 uvp[3] = vp[1] + 0x80;
625 uvp[4] = up[2] + 0x80;
626 uvp[5] = vp[2] + 0x80;
627 uvp[6] = up[3] + 0x80;
628 uvp[7] = vp[3] + 0x80;
629 uvp += 8;
630 up += width >> 1;
631 vp += width >> 1;
632 }
633 uvp = uvblk;
634 #define width 8
635
636 dataptr = block;
637 for (i=0; i<8; i++) {
638 t0 = uvp[0];
639 t1 = uvp[7*width];
640 a0 = t0+t1;
641 c3 = t0-t1;
642 uvp += width;
643
644 t0 = uvp[0];
645 t1 = uvp[5*width];
646 a1 = t0+t1;
647 c2 = t0-t1;
648 uvp += width;
649
650 t0 = uvp[0];
651 t1 = uvp[3*width];
652 a2 = t0+t1;
653 c1 = t0-t1;
654 uvp += width;
655
656 t0 = uvp[0];
657 t1 = uvp[width];
658 a3 = t0+t1;
659 c0 = t0-t1;
660 uvp -= 3*width;
661
662 b0 = a0+a3;
663 b1 = a1+a2;
664 b2 = a1-a2;
665 b3 = a0-a3;
666
667 dataptr[0] = (362 * (b0+b1)) >> 7;
668 dataptr[32] = (362 * (b0-b1)) >> 7;
669 dataptr[16] = (196*b2 + 473*b3) >> 7;
670 dataptr[48] = (196*b3 - 473*b2) >> 7;
671
672 b0 = (362 * (c2-c1)) >> 7;
673 b1 = (362 * (c2+c1)) >> 7;
674 c0 = c0 << 2;
675 c3 = c3 << 2;
676
677 a0 = c0+b0;
678 a1 = c0-b0;
679 a2 = c3-b1;
680 a3 = c3+b1;
681
682 dataptr[8] = (100*a0 + 502*a3) >> 9;
683 dataptr[24] = (426*a2 - 284*a1) >> 9;
684 dataptr[40] = (426*a1 + 284*a2) >> 9;
685 dataptr[56] = (100*a3 - 502*a0) >> 9;
686
687
688 uvp++;
689 dataptr++;
690 }
691
692 dataptr = block;
693 for (i=0; i<8; i++) {
694 a0 = dataptr[0];
695 a3 = dataptr[6];
696
697 a1 = dataptr[2];
698 a2 = dataptr[4];
699
700 b0 = a0+a3;
701 b1 = a1+a2;
702 b2 = a1-a2;
703 b3 = a0-a3;
704
705 outcptr[0] = (362 * (b0+b1) + 16384) >> 15;
706 outcptr[4] = (362 * (b0-b1) + 16384) >> 15;
707 outcptr[2] = (196*b2 + 473*b3 + 16384) >> 15;
708 outcptr[6] = (196*b3 - 473*b2 + 16384) >> 15;
709
710 a0 = dataptr[1];
711 a3 = dataptr[7];
712
713 a1 = dataptr[3];
714 a2 = dataptr[5];
715
716 b0 = a0+a3;
717 b1 = a1+a2;
718 b2 = a1-a2;
719 b3 = a0-a3;
720
721 outcptr[1] = (362 * (b0+b1) + 16384) >> 15;
722 outcptr[5] = (362 * (b0-b1) + 16384) >> 15;
723 outcptr[3] = (196*b2 + 473*b3 + 16384) >> 15;
724 outcptr[7] = (196*b3 - 473*b2 + 16384) >> 15;
725
726 dataptr += 8;
727 outcptr += 8;
728 }
729 #undef width
730 }
731 }
732
733
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.