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

Open Mash Cross Reference
mash/codec/compositor.cc

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

  1 /*
  2  * compositor.cc --
  3  *
  4  *      Overlay and Compositor Class object source code.
  5  *
  6  * Copyright (c) 1995-2002 The Regents of the University of California.
  7  * All rights reserved.
  8  *
  9  * Redistribution and use in source and binary forms, with or without
 10  * modification, are permitted provided that the following conditions are met:
 11  *
 12  * A. Redistributions of source code must retain the above copyright notice,
 13  *    this list of conditions and the following disclaimer.
 14  * B. Redistributions in binary form must reproduce the above copyright notice,
 15  *    this list of conditions and the following disclaimer in the documentation
 16  *    and/or other materials provided with the distribution.
 17  * C. Neither the names of the copyright holders nor the names of its
 18  *    contributors may be used to endorse or promote products derived from this
 19  *    software without specific prior written permission.
 20  *
 21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
 22  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 23  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
 25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 31  * POSSIBILITY OF SUCH DAMAGE.
 32  */
 33 
 34 #ifndef lint
 35 static const char rcsid[] =
 36     "@(#) $Header: /usr/mash/src/repository/mash/mash-1/codec/compositor.cc,v 1.14 2002/05/21 21:18:12 chema Exp $";
 37 #endif
 38 
 39 #include <stdlib.h>
 40 #ifndef WIN32
 41 #include <unistd.h>
 42 #endif
 43 #include <string.h>
 44 #include <sys/types.h>
 45 #include <sys/stat.h>
 46 #include <fcntl.h>
 47 #ifdef WIN32
 48 #include <io.h>
 49 #else
 50 #include <sys/file.h>
 51 #endif
 52 #include "module.h"
 53 #include "crdef.h"
 54 
 55 class Overlay : public TclObject {
 56 public:
 57         Overlay();
 58         inline int width() const { return (width_); }
 59         inline int height() const { return (height_); }
 60         inline const u_char* image() const { return (image_); }
 61         inline int transparent() const { return (transparent_); }
 62 protected:
 63         int command(int argc, const char*const* argv);
 64         int load(const char* file, int w, int h);
 65         int width_;
 66         int height_;
 67         u_char* image_;
 68         int transparent_; /* transparent luminance */
 69 };
 70 
 71 static class OverlayClass : public TclClass {
 72 public:
 73         OverlayClass() : TclClass("Overlay") {}
 74         TclObject* create(int /* argc */, const char*const* /* argv */) {
 75                 return (new Overlay());
 76         }
 77 } matcher_overlay;
 78 
 79 class Compositor : public FrameModule {
 80  public:
 81         Compositor();
 82         ~Compositor();
 83  protected:
 84         void reset();
 85         int command(int argc, const char*const* argv);
 86         void crinit(int w, int h);
 87         u_char* frm_;
 88         u_char* framebase_;
 89         u_char* damage_;
 90         struct onode {
 91                 Overlay* overlay;
 92                 int x;
 93                 int y;
 94                 int depth;
 95                 onode* next;
 96         };
 97         void attach(Overlay* o, int x, int y, int depth);
 98         void move(Overlay*, int x, int y);
 99         void detach(Overlay*);
100         void damage(onode*);
101         onode* overlays_;
102 };
103 
104 class Compositor422 : public Compositor {
105 public:
106         virtual void recv(Buffer*);
107         void size(int w, int h);
108         void copy_block(u_char* ofrm, u_char* ochm,
109                         const u_char* frm, const u_char* chm);
110         void composite(Overlay* o, int x, int y);
111 };
112 
113 class Compositor420 : public Compositor {
114 public:
115         virtual void recv(Buffer*);
116         void size(int w, int h);
117         void copy_block(u_char* ofrm, u_char* ochm,
118                         const u_char* frm, const u_char* chm);
119         void composite(Overlay* o, int x, int y);
120 };
121 
122 static class Compositor422Class : public TclClass {
123 public:
124         Compositor422Class() : TclClass("Module/Compositor/422") {}
125         TclObject* create(int /* argc */, const char*const* /* argv */) {
126                 return (new Compositor422);
127         }
128 } compositor422;
129 
130 static class Compositor420Class : public TclClass {
131 public:
132         Compositor420Class() : TclClass("Module/Compositor/420") {}
133         TclObject* create(int /* argc */, const char*const* /* argv */) {
134                 return (new Compositor420);
135         }
136 } compositor420;
137 
138 Overlay::Overlay() : width_(0), height_(0), image_(0), transparent_(0)
139 {
140 }
141 
142 int Overlay::command(int argc, const char*const* argv)
143 {
144         Tcl& tcl = Tcl::instance();
145         if (argc == 3) {
146                 if (strcmp(argv[1], "transparent") == 0) {
147                         transparent_ = atoi(argv[2]);
148                         return (TCL_OK);
149                 }
150         } else if (argc == 5) {
151                 if (strcmp(argv[1], "load") == 0) {
152                         const char* file = argv[2];
153                         int w = atoi(argv[3]);
154                         int h = atoi(argv[4]);
155                         if (load(file, w, h) < 0)
156                                 tcl.result("-1");
157                         else
158                                 tcl.result("");
159                         return (TCL_OK);
160                 }
161         }
162         return (TclObject::command(argc, argv));
163 }
164 
165 int Overlay::load(const char* file, int w, int h)
166 {
167         delete[] image_;
168         image_ = 0;
169         int fd = open(file, O_RDONLY);
170         if (fd < 0)
171                 return (-1);
172         width_ = w;
173         height_ = h;
174         int s = 2 * w * h;
175         image_ = new u_char[s];
176         int cc = read(fd, image_, s);
177         if (cc != s) {
178                 delete[] image_;
179                 image_ = 0;
180                 return (-1);
181         }
182         close(fd);
183         return (0);
184 }
185 
186 Compositor::Compositor()
187         : frm_(0), framebase_(0), damage_(0)
188 {
189         width_ = 0;
190         height_ = 0;
191         framesize_ = 0;
192         overlays_ = 0;
193 }
194 
195 Compositor::~Compositor()
196 {
197         delete[] framebase_;
198         delete[] damage_;
199         onode* p = overlays_;
200         while (p != 0) {
201                 onode* n = p->next;
202                 delete p;
203                 p = n;
204         }
205 }
206 
207 int Compositor::command(int argc, const char*const* argv)
208 {
209         Tcl& tcl = Tcl::instance();
210         if (argc == 2) {
211                 if (strcmp(argv[1], "reset") == 0) {
212                         reset();
213                         return (TCL_OK);
214                 }
215         } else if (argc == 3) {
216                 if (strcmp(argv[1], "detach") == 0) {
217                         Overlay* o = (Overlay*)TclObject::lookup(argv[2]);
218                         if (o == 0) {
219                                 tcl.result("no such overlay");
220                                 return (TCL_ERROR);
221                         }
222                         detach(o);
223                         return (TCL_OK);
224                 }
225         } else if (argc == 5) {
226                 if (strcmp(argv[1], "move") == 0) {
227                         Overlay* o = (Overlay*)TclObject::lookup(argv[2]);
228                         if (o == 0) {
229                                 tcl.result("no such overlay");
230                                 return (TCL_ERROR);
231                         }
232                         int x = atoi(argv[3]);
233                         int y = atoi(argv[4]);
234                         move(o, x, y);
235                         return (TCL_OK);
236                 }
237         } else if (argc == 6) {
238                 if (strcmp(argv[1], "attach") == 0) {
239                         Overlay* o = (Overlay*)TclObject::lookup(argv[2]);
240                         if (o == 0) {
241                                 tcl.result("no such overlay");
242                                 return (TCL_ERROR);
243                         }
244                         int x = atoi(argv[3]);
245                         int y = atoi(argv[4]);
246                         int depth = atoi(argv[5]);
247                         attach(o, x, y, depth);
248                         return (TCL_OK);
249                 }
250         }
251         return (FrameModule::command(argc, argv));
252 }
253 
254 void Compositor::reset()
255 {
256         while (overlays_)
257                 detach(overlays_->overlay);
258 }
259 
260 void Compositor::attach(Overlay* o, int x, int y, int depth)
261 {
262         x &=~ 1;
263         y &=~ 1;
264         onode* p = new onode;
265         p->overlay = o;
266         p->x = x;
267         p->y = y;
268         p->depth = depth;
269         onode** op;
270         for (op = &overlays_; *op != 0; op = &(*op)->next)
271                 if (depth > (*op)->depth)
272                         break;
273         p->next = *op;
274         *op = p;
275         damage(p);
276 }
277 
278 void Compositor::detach(Overlay* /* o */)
279 {
280         for (onode** op = &overlays_; *op != 0; op = &(*op)->next) {
281                 onode* p = (*op)->next;
282                 if (*op == p) {
283                         damage(p);
284                         *op = p->next;
285                         delete p;
286                         return;
287                 }
288         }
289 }
290 
291 void Compositor::move(Overlay* o, int x, int y)
292 {
293         x &=~ 1;
294         y &=~ 1;
295         for (onode* p = overlays_; p != 0; p = p->next) {
296                 if (p->overlay == o) {
297                         damage(p);
298                         p->x = x;
299                         p->y = y;
300                         damage(p);
301                         return;
302                 }
303         }
304 }
305 
306 /*
307  * the overlay in onode will be added, deleted or moved.
308  * update the damage vector so we send the corresponding
309  * blocks to reflect change.
310  */
311 void Compositor::damage(onode* on)
312 {
313         int blkw = width_ >> 4;
314         int blkh = height_ >> 4;
315         int bx = on->x >> 4;
316         int bw = ((on->x + on->overlay->width() + 15) >> 4) - bx;
317         if (bx + bw > blkw)
318                 bw = blkw - bx;
319         int by = on->y >> 4;
320         int bh = ((on->y + on->overlay->height() + 15) >> 4) - by;
321         if (by + bh > blkh)
322                 bh = blkh - by;
323 
324         u_char* p = &damage_[blkw * by + bx];
325         while (--bh >= 0) {
326                 for (int k = 0; k < bw; ++k)
327                         p[k] = 1;
328                 p += blkw;
329         }
330 }
331 
332 void Compositor::crinit(int w, int h)
333 {
334         int blkw = w >> 4;
335         int blkh = h >> 4;
336         int n = blkw * blkh;
337         delete[] damage_;
338         damage_ = new u_char[n];
339         memset(damage_, 0, n);
340 }
341 
342 /*FIXME*/
343 #define VIDCAP_VPAD 1
344 void Compositor422::size(int w, int h)
345 {
346         FrameModule::size(w, h);
347         int n = 2 * framesize_ + 2 * VIDCAP_VPAD * w;
348         delete[] framebase_;
349         framebase_ = new u_char[n];
350         frm_ = framebase_ + VIDCAP_VPAD * w;
351         Compositor::crinit(w, h);
352 }
353 
354 void Compositor422::copy_block(u_char* ofrm, u_char* ochm,
355                          const u_char* frm, const u_char* chm)
356 {
357         int stride = width_;
358         int k;
359         for (k = 16; --k >= 0; ) {
360                 *(int32_t*)&ofrm[0] = *(int32_t*)&frm[0];
361                 *(int32_t*)&ofrm[4] = *(int32_t*)&frm[4];
362                 *(int32_t*)&ofrm[8] = *(int32_t*)&frm[8];
363                 *(int32_t*)&ofrm[12] = *(int32_t*)&frm[12];
364                 ofrm += stride;
365                 frm += stride;
366         }
367         stride >>= 1;
368         for (k = 16; --k >= 0; ) {
369                 *(int32_t*)&ochm[0] = *(int32_t*)&chm[0];
370                 *(int32_t*)&ochm[4] = *(int32_t*)&chm[4];
371                 ochm += stride;
372                 chm += stride;
373         }
374         ochm -= stride << 4;
375         ochm += framesize_ >> 1;
376         chm -= stride << 4;
377         chm += framesize_ >> 1;
378         for (k = 16; --k >= 0; ) {
379                 *(int32_t*)&ochm[0] = *(int32_t*)&chm[0];
380                 *(int32_t*)&ochm[4] = *(int32_t*)&chm[4];
381                 ochm += stride;
382                 chm += stride;
383         }
384 }
385 
386 void Compositor422::recv(Buffer* bp)
387 {
388         const VideoFrame* vf = (VideoFrame*)bp;
389         if (!samesize(vf))
390                 size(vf->width_, vf->height_);
391         YuvFrame* p = (YuvFrame*)vf;
392 
393         /*
394          * 1. update our copy of the frame
395          * 2. composite all compositor items (and update crvec)
396          */
397         int blkw = width_ >> 4;
398         int blkh = height_ >> 4;
399         int blkno = 0;
400 
401         int loff = 0;
402         int coff = 0;
403         int fs = framesize_;
404         u_int8_t* dam = damage_;
405         const u_int8_t* crv = p->crvec_;
406         u_int8_t* frm = p->bp_;
407         for (int y = 0; y < blkh; ++y) {
408                 for (int x = 0; x < blkw; ++blkno, loff += 16, coff += 8,
409                      ++x, ++crv, ++dam) {
410                         /* smash damage array into a crvec */
411                         int d = *dam;
412                         if (d)
413                                 d = CR_LQ|CR_MOTION_BIT;
414                         else
415                                 d = *crv;
416                         *dam = d;
417                         if (d & CR_SEND) {
418                                 copy_block(frm_ + loff, frm_ + fs + coff,
419                                            frm + loff, frm + fs + coff);
420                         }
421                 }
422                 loff += 15 * width_;
423                 coff += 15 * (width_ >> 1);
424         }
425         for (onode* o = overlays_; o != 0; o = o->next)
426                 composite(o->overlay, o->x, o->y);
427         YuvFrame nf(p->ts_, frm_, damage_, p->width_, p->height_, 422);
428         target_->recv(&nf);
429         memset(damage_, 0, blkw * blkh);
430 }
431 
432 void Compositor422::composite(Overlay* o, int x, int y)
433 {
434         if (x >= width_ || y >= height_)
435                 return;
436 
437         int off = y * width_ + x;
438         u_char* yp = frm_ + off;
439         u_char* up = frm_ + framesize_ + (off >> 1);
440         u_char* vp = up + (framesize_ >> 1);
441         int w = o->width();
442         int h = o->height();
443         if (x + w > width_)
444                 w = width_ - x;
445         if (y + h > height_)
446                 h = height_ - y;
447         const u_char* p = o->image();
448         if (p == 0)
449                 return;
450         int trans = o->transparent();
451         while (--h >= 0) {
452                 /* two pixels at a time */
453                 for (int k = 0; k < w; k += 2) {
454                         if (p[0] != trans) {
455                                 yp[k] = p[0];
456                                 yp[k + 1] = p[2];
457                                 up[k >> 1] = p[1];
458                                 vp[k >> 1] = p[3];
459                         }
460                         p += 4;
461                 }
462                 yp += width_;
463                 up += width_ >> 1;
464                 vp += width_ >> 1;
465                 p += (o->width() - w) << 1;
466         }
467 }
468 
469 void Compositor420::size(int w, int h)
470 {
471         FrameModule::size(w, h);
472         int fs = framesize_;
473         int n = fs + (fs >> 1) + 2 * VIDCAP_VPAD * w;
474         delete[] framebase_;
475         framebase_ = new u_char[n];
476         frm_ = framebase_ + VIDCAP_VPAD * w;
477         Compositor::crinit(w, h);
478 }
479 
480 void Compositor420::copy_block(u_char* ofrm, u_char* ochm,
481                             const u_char* frm, const u_char* chm)
482 {
483         int stride = width_;
484         int k;
485         for (k = 16; --k >= 0; ) {
486                 *(int32_t*)&ofrm[0] = *(int32_t*)&frm[0];
487                 *(int32_t*)&ofrm[4] = *(int32_t*)&frm[4];
488                 *(int32_t*)&ofrm[8] = *(int32_t*)&frm[8];
489                 *(int32_t*)&ofrm[12] = *(int32_t*)&frm[12];
490                 ofrm += stride;
491                 frm += stride;
492         }
493         stride >>= 1;
494         for (k = 8; --k >= 0; ) {
495                 *(int32_t*)&ochm[0] = *(int32_t*)&chm[0];
496                 *(int32_t*)&ochm[4] = *(int32_t*)&chm[4];
497                 ochm += stride;
498                 chm += stride;
499         }
500         ochm -= stride << 3;
501         ochm += framesize_ >> 2;
502         chm -= stride << 3;
503         chm += framesize_ >> 2;
504         for (k = 8; --k >= 0; ) {
505                 *(int32_t*)&ochm[0] = *(int32_t*)&chm[0];
506                 *(int32_t*)&ochm[4] = *(int32_t*)&chm[4];
507                 ochm += stride;
508                 chm += stride;
509         }
510 }
511 
512 void Compositor420::recv(Buffer* bp)
513 {
514         const VideoFrame* vf = (VideoFrame*)bp;
515         if (!samesize(vf))
516                 size(vf->width_, vf->height_);
517         YuvFrame* p = (YuvFrame*)vf;
518 
519         int blkw = width_ >> 4;
520         int blkh = height_ >> 4;
521         int blkno = 0;
522 
523         int loff = 0;
524         int coff = 0;
525         int fs = framesize_;
526         u_char* dam = damage_;
527         const u_int8_t* crv = p->crvec_;
528         u_int8_t* frm = p->bp_;
529         for (int y = 0; y < blkh; ++y) {
530                 for (int x = 0; x < blkw; ++blkno, loff += 16, coff += 8,
531                      ++x, ++crv, ++dam) {
532                         /* smash damage array into a crvec */
533                         int d = *dam;
534                         if (d)
535                                 d = CR_LQ|CR_MOTION_BIT;
536                         else
537                                 d = *crv;
538                         *dam = d;
539                         if (d & CR_SEND) {
540                                 copy_block(frm_ + loff, frm_ + fs + coff,
541                                            frm + loff, frm + fs + coff);
542                         }
543                 }
544                 loff += 15 * width_;
545                 coff += 7 * (width_ >> 1);
546         }
547         for (onode* o = overlays_; o != 0; o = o->next)
548                 composite(o->overlay, o->x, o->y);
549 
550         YuvFrame nf(p->ts_, frm_, damage_, p->width_, p->height_, 420);
551         target_->recv(&nf);
552         memset(damage_, 0, blkw * blkh);
553 }
554 
555 void Compositor420::composite(Overlay* o, int x, int y)
556 {
557         if (x >= width_ || y >= height_)
558                 return;
559 
560         int off = y * width_;
561         u_char* yp = frm_ + off + x;
562         off = (off >> 2) + (x >> 1);
563         u_char* up = frm_ + framesize_ + off;
564         u_char* vp = up + (framesize_ >> 2);
565         int ovw = o->width();
566         int w = ovw;
567         int h = o->height();
568         if (x + w > width_)
569                 w = width_ - x;
570         if (y + h > height_)
571                 h = height_ - y;
572         const u_char* p = o->image();
573         if (p == 0)
574                 return;
575         int trans = o->transparent();
576 
577         /* convert to byte offset */
578         ovw <<= 1;
579 
580         for (; h > 0; h -= 2) {
581                 /* two pixels at a time, both horiz and vertically */
582                 for (int k = 0; k < w; k += 2) {
583                         if (p[0] != trans) {
584                                 yp[k] = p[0];
585                                 yp[k + width_] = p[ovw];
586                                 yp[k + 1] = p[2];
587                                 yp[k + 1 + width_] = p[ovw + 2];
588                                 up[k >> 1] = p[1];
589                                 vp[k >> 1] = p[3];
590                         }
591                         p += 4;
592                 }
593                 yp += width_ << 1;
594                 up += width_ >> 1;
595                 vp += width_ >> 1;
596                 p += (ovw - w) << 1;
597         }
598 }
599 

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