root/vic/trunk/video/grabber-mme.cpp @ 905

Revision 905, 22.6 KB (checked in by piers, 15 years ago)

New dir: video - all things to do with grabbing

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * Copyright (c) 1993-1994 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by the University of
16 *      California, Berkeley and the Network Research Group at
17 *      Lawrence Berkeley Laboratory.
18 * 4. Neither the name of the University nor of the Laboratory may be used
19 *    to endorse or promote products derived from this software without
20 *    specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#ifndef lint
36static char rcsid[] =
37    "@(#) $Header$ (LBL)";
38#endif
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <errno.h>
43#include <string.h>
44#ifndef __DECCXX
45#include <osfcn.h>
46#endif
47#include <sys/file.h>
48#include <sys/stat.h>
49
50extern "C" {
51/*XXX*/
52#undef VOID
53#include <mme/mme_api.h>
54}
55
56#include "inet.h"
57#include "vic_tcl.h"
58#include "rtp.h"
59#include "grabber.h"
60#include "iohandler.h"
61#include "device-input.h"
62#include "crdef.h"
63#include "module.h"
64
65#define NTSC_WIDTH 640
66#define NTSC_HEIGHT 480
67
68extern "C" {
69#include <tcl.h>
70#include <sys/types.h>
71#include <sys/ipc.h>
72#include <sys/shm.h>
73}
74
75class MmeGrabber : public Grabber, public IOHandler {
76public:
77        MmeGrabber();
78        virtual ~MmeGrabber();
79        virtual int command(int argc, const char*const* argv);
80        virtual void fps(int);
81        virtual void start();
82        virtual void stop();
83protected:
84        virtual void SetComp() = 0;
85        void setport(const char *port);
86        void setstandard(const char *standard);
87        virtual void dispatch(int mask);
88        virtual void timeout();
89        virtual int consume(const u_char* dmabuf, int length) = 0;
90        virtual const char* type() const;
91        virtual void startup();
92        virtual void shutdown();
93        virtual int grab();
94        inline int mme_error(MMRESULT, const char* msg) const;
95        static int server_;     /* fd of server socket */
96        HVIDEO handle_;         /* handle for video connection */
97        int x_decimate_;        /* horizontal downsampling factor */
98        int y_decimate_;        /* vertical downsampling factor */
99        struct info {
100                EXBMINFOHEADER b;
101                JPEGINFOHEADER jpeg;
102        } *bmh;
103private:
104        void init();
105        VIDEOHDR* vh_;
106        static void mme_callback(HVIDEO handle, DWORD code, DWORD instance,
107                                 LPARAM p1, LPARAM p2);
108        int callback(int code, VIDEOHDR* vh);
109        void waitgrab();
110
111        int port_;
112        int standard_;
113        int fps_;
114        int delay_;
115        int last_grab_;
116        volatile int outstanding_;
117
118        volatile int running_;
119        volatile int valid_;
120        volatile int wantgrab_;
121        int buffers_;
122};
123
124class MmeJpegGrabber : public MmeGrabber {
125public:
126        MmeJpegGrabber();
127        virtual ~MmeJpegGrabber();
128        virtual int command(int argc, const char*const* argv);
129protected:
130        int consume(const u_char* buffer, int length);
131        virtual void SetComp();
132private:
133        int q_;
134        int nq_;
135};
136
137class MmeYuvGrabber : public MmeGrabber {
138public:
139        MmeYuvGrabber();
140        virtual void SetComp();
141        virtual int consume(const u_char* buffer, int length);
142protected:
143        void suppress(const u_char* devbuf, const u_char* lumbuf);
144        virtual void saveblks(const u_char* in) = 0;
145        virtual void setsize(int w, int h) = 0;
146};
147
148class Mme422Grabber : public MmeYuvGrabber {
149protected:
150        virtual void saveblks(const u_char* in);
151        void saveblk(const u_char* in, u_char* yp, u_char* up,
152                     u_char* vp, int stride);
153        void setsize(int w, int h);
154};
155
156class MmeCIFGrabber : public MmeYuvGrabber {
157protected:
158        virtual void saveblks(const u_char* in);
159        void saveblk(const u_char* in, u_char* yp, u_char* up,
160                     u_char* vp, int stride, int istride);
161        void setsize(int w, int h);
162};
163
164
165class Mme411Grabber : public MmeCIFGrabber {
166    protected:
167        virtual void setsize(int xsize, int ysize);
168};
169
170class MmeDevice : public InputDevice {
171 public:
172        MmeDevice(const char* name);
173        virtual int command(int argc, const char*const* argv);
174        static int havedev();
175};
176
177/***********************************************************************/
178
179static MmeDevice mme_device("mme");
180
181int MmeDevice::havedev()
182{
183    /* tfm - need to do a more thorough check here */
184    if( videoGetNumDevs() > 0 )
185      return (1);
186    else
187      return (0);
188}
189
190MmeDevice::MmeDevice(const char* name) : InputDevice(name)
191{
192    /* fprintf(stderr, "vic: Called MmeDevice::MmeDevice\n"); */
193    if (havedev())
194      attributes_ = "format { 422 jpeg } size { small large cif } port {Comp-1 Comp-2 S-Video525 S-Video625}";
195    else
196      attributes_ = "disabled";
197}
198
199int MmeDevice::command(int argc, const char*const* argv)
200{
201    Tcl& tcl = Tcl::instance();
202    if (argc == 3) {
203        if(strcmp(argv[1], "open") == 0) {
204            const char* fmt = argv[2];
205            TclObject* o = 0;
206            /* fprintf(stderr, "vic: Called MmeDevice::command with %s %s\n",
207                    argv[1],argv[2]); */
208            if (strcmp(fmt, "jpeg") == 0)
209              o = new MmeJpegGrabber;
210            else if (strcmp(fmt, "422") == 0)
211              o = new Mme422Grabber;
212            else if (strcmp(fmt, "411") == 0)
213              o = new Mme411Grabber;
214            else if (strcmp(fmt, "cif") == 0)
215              o = new MmeCIFGrabber;
216            if (o != 0) {
217                Tcl::instance().result(o->name());
218                return (TCL_OK);
219            }
220        }
221    }
222    return (InputDevice::command(argc, argv));
223}
224
225
226/***********************************************************************/
227
228MmeGrabber* mmeMaster;
229
230
231MmeGrabber::MmeGrabber()
232{
233        /* fprintf(stderr, "vic: Called MmeGrabber constructor\n"); */
234        mmeMaster = this;
235
236        /*XXX defer videoOpen until start? */
237        if (videoGetNumDevs() <= 0 ||
238            videoOpen(&handle_, 0, VIDEO_IN) != DV_ERR_OK) {
239                valid_ = 0;
240                fprintf(stderr,"vic : Failed to open video device\n");
241                return;
242        }
243
244        port_=1;
245        standard_=VIDEO_STANDARD_NTSC;
246
247        valid_ = 1;
248        running_ = 0;
249        wantgrab_ = 0;
250        buffers_ = 1;
251   
252        fps(5);
253        init();
254}
255
256MmeGrabber::~MmeGrabber()
257{
258    /* fprintf(stderr, "vic: Called MmeGrabber::~MmeGrabber\n"); */
259        if (valid_) {
260                if (running_)
261                        stop();
262                mmeFreeMem(vh_);
263                videoClose(handle_);
264        }
265}
266
267const char* MmeGrabber::type() const
268{
269        return ("mme");
270}
271
272int MmeGrabber::server_ = -1;
273
274void MmeGrabber::init()
275{
276        int size;
277        MMRESULT s;
278
279    /* fprintf(stderr, "vic: Called MmeGrabber::init\n"); */
280        /*
281         * Allocate & zero some memory for the video header and bitmap
282         * info header.  We allocate it as a single block to keep it
283         * all in one shared memory segment.
284         * (Make sure everything's aligned on quadword boundaries)
285         */
286        size = ((sizeof(*bmh)+sizeof(void*)-1) / sizeof(void*)) * sizeof(void*);
287        bmh = (info*)mmeAllocMem(size+sizeof(*vh_));
288        if (bmh == 0) {
289                fprintf(stderr, "vic: cannot allocate mme memory\n");
290                valid_ = 0;
291                return;
292        }
293        memset(bmh, 0, size+sizeof(*vh_));
294        vh_ = (VIDEOHDR*)((char*)bmh+size);
295
296
297        if (server_ < 0) {
298                server_ = mmeServerFileDescriptor();
299                link(server_, TK_READABLE);
300        }
301
302        return;
303 bail:
304        mmeFreeMem(bmh);
305        bmh = 0;
306        videoClose(handle_);
307        vh_ = 0;
308        valid_ = 0;
309        /*XXX*/
310}
311
312/* Override Grabber's timeout method with an empty method */
313void MmeGrabber::timeout()
314{
315}
316
317int MmeGrabber::command(int argc, const char*const* argv)
318{
319    Tcl& tcl = Tcl::instance();
320    if (argc == 3) {
321        if(strcmp(argv[1], "decimate") == 0) {
322            int d = atoi(argv[2]);
323            /* fprintf(stderr, "vic: Called MmeGrabber::command with %s %s\n",
324                    argv[1],argv[2]); */
325            if (d == 0) {
326                tcl.resultf("%s: divide by zero", argv[0], 0);
327                return (TCL_ERROR);
328            }
329            x_decimate_ = d;
330            y_decimate_ = d;
331            if(running_) {
332                shutdown();
333                SetComp();
334                startup();
335            }
336            else
337              SetComp();
338           
339            return (TCL_OK);
340        }
341        else if (strcmp(argv[1], "port") == 0) {
342            setport(argv[2]);
343            return(TCL_OK);
344        }
345        else if (strcmp(argv[1], "type") == 0) {
346            setstandard(argv[2]);
347            return(TCL_OK);
348        }
349    }
350    return (Grabber::command(argc, argv));
351}
352
353void MmeGrabber::start()
354{
355    /* fprintf(stderr, "vic: Called MmeGrabber::start\n"); */
356        startup();
357        Grabber::start();
358}
359
360void MmeGrabber::stop()
361{
362    /* fprintf(stderr, "vic: Called MmeGrabber::stop\n"); */
363        shutdown();
364        Grabber::stop();
365}
366
367void MmeGrabber::fps(int f)
368{
369        /* fprintf(stderr, "vic: Called MmeGrabber::fps\n"); */
370        fps_ = f;
371        delay_ = 1000 / f;
372        Grabber::fps(f);
373}
374
375
376void MmeGrabber::setport(const char *port)
377{
378    if(port) {
379        if(strcmp(port,"Comp-1") == 0)
380          port_=1;
381        else if(strcmp(port,"Comp-2") == 0)
382          port_=2;
383        else if(strcmp(port,"S-Video525") == 0) {
384            port_ = 0;
385            standard_ = VIDEO_STANDARD_SVIDEO525;
386        }
387        else if(strcmp(port,"S-Video625") == 0) {
388            port_ = 0;
389            standard_ = VIDEO_STANDARD_SVIDEO625;
390        }
391    }
392}
393void MmeGrabber::setstandard(const char *standard)
394{
395    if(standard) {
396        if(strcmp(standard,"ntsc") == 0) {
397            standard_=VIDEO_STANDARD_NTSC;
398            if(!port_)
399              port_=1;
400        }
401        else if(strcmp(standard,"pal") == 0) {
402            standard_=VIDEO_STANDARD_PAL;
403            if(!port_)
404              port_=1;
405        }
406        else if(strcmp(standard,"secam") == 0) {
407            standard_=VIDEO_STANDARD_SECAM;
408            if(!port_)
409              port_=1;
410        }
411        else if(strcmp(standard,"svideo525") == 0)
412          standard_=VIDEO_STANDARD_SVIDEO525;
413        else if(strcmp(standard,"svideo625") == 0)
414          standard_=VIDEO_STANDARD_SVIDEO625;
415    }
416}
417
418void MmeGrabber::startup()
419{
420    MMRESULT s;
421    int size;
422   
423    /* fprintf(stderr, "vic: Called MmeGrabber::startup\n"); */
424   
425    if (running_)
426      return;
427   
428    if(port_) {
429        s=videoSetPortNum(handle_,port_);
430        if (mme_error(s, "couldn't configure mme"))
431          goto bail;
432    }
433
434    if(standard_) {
435        s=videoSetStandard(handle_,standard_);
436        if (mme_error(s, "couldn't configure mme"))
437          goto bail;
438    }
439
440    s = videoConfigure(handle_, DVM_FORMAT,
441                       VIDEO_CONFIGURE_GET|VIDEO_CONFIGURE_MIN,
442                       0, bmh, sizeof(*bmh), 0, 0);
443    size = bmh->b.bmi.biSizeImage;/*XXX ridiculously large*/
444    s = videoConfigure(handle_, DVM_FORMAT, VIDEO_CONFIGURE_SET,
445                       0, bmh, sizeof(*bmh), 0, 0);
446    if (mme_error(s, "couldn't configure mme"))
447      goto bail;
448       
449#ifdef notdef
450        size = 320 * 240 * 3;
451#endif
452        vh_->lpData = (LPSTR)mmeAllocBuffer(size);
453        if (vh_->lpData == 0) {
454                fprintf(stderr, "vic: couldn't allocate mme frame memory\n");
455                goto bail;
456        }
457        vh_->dwBufferLength = size;
458       
459       
460        s = videoStreamInit(handle_, 1000000 /*10fps - ignored */,
461                            mme_callback,
462                            0, CALLBACK_FUNCTION);
463        if (mme_error(s, "couldn't initialize mme stream\n"))
464                return;
465        s = videoStreamPrepareHeader(handle_, vh_, sizeof(*vh_));
466        if (mme_error(s, "couldn't prepare mme video hdr"))
467                return;
468        s = videoStreamStart(handle_);
469        if (mme_error(s, "couldn't start mme video stream\n"))
470                return;
471        running_ = 1;
472        frameclock_ = gettimeofday();
473
474        outstanding_ = 0;
475        last_grab_ = 0;
476
477        grab();
478        return;
479
480bail:
481        mmeFreeMem(bmh);
482        bmh = 0;
483        videoClose(handle_);
484        vh_ = 0;
485        valid_ = 0;
486}
487
488void MmeGrabber::shutdown()
489{
490        MMRESULT s;
491
492        /* fprintf(stderr, "vic: Called MmeGrabber::shutdown\n"); */
493        if (!running_)
494                return;
495
496        wantgrab_ = 0;
497        running_ = 0;
498        s = videoStreamReset(handle_);
499        (void)mme_error(s, "couldn't reset mme stream");
500        while(outstanding_) {
501                mmeWaitForCallbacks();
502                mmeProcessCallbacks();
503        }
504        s = videoStreamUnprepareHeader(handle_, vh_, sizeof(*vh_));
505        (void)mme_error(s, "couldn't unprepare mme video header");
506        s = videoStreamFini(handle_);
507        (void)mme_error(s, "couldn't shutdown mme stream");
508        running_ = 0;
509
510
511        mmeFreeBuffer(vh_->lpData);
512}
513
514
515/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
516
517inline int MmeGrabber::mme_error(MMRESULT code, const char* msg) const
518{
519        if (code != DV_ERR_OK) {
520            char *buffer;
521            if(buffer=(char *)mmeAllocMem(MAXERRORLENGTH)) {
522                videoGetErrorText(handle_,code,buffer,MAXERRORLENGTH);
523                fprintf(stderr, "vic: %s - %s (%d)\n", msg, buffer, code);
524                mmeFreeMem(buffer);
525            }
526
527            return (1);
528        }
529        return (0);
530}
531
532extern "C" {
533void MmeGrabber::mme_callback(HVIDEO handle, DWORD code, DWORD instance,
534                              LPARAM vh, LPARAM p2)
535{
536#ifdef notyet
537        MmeGrabber* p = (MmeGrabber*)instance;
538    fprintf(stderr, "vic: Called MmeGrabber::mme_callback\n");
539        p->callback();
540#else
541        (void)mmeMaster->callback(code, (VIDEOHDR*)vh);
542#endif
543}
544}
545
546int MmeGrabber::callback(int code, VIDEOHDR *vh)
547{
548        int n;
549
550        /* fprintf(stderr, "vic: Called MmeGrabber::callback\n"); */
551
552        /* Nothing to do for open or close - just dismiss */
553        if (code == MM_DRVM_OPEN || code == MM_DRVM_CLOSE)
554                return (1);
555
556        if (code != MM_DRVM_DATA) {
557                fprintf(stderr,"vic: mme callback code %d\n", code);
558                return (0);
559        }
560
561        if (vh->lpData != vh_->lpData)
562                fprintf(stderr,"vic: buffer address changed in callback\n");
563               
564        if ((vh->dwFlags & VHDR_DONE) == 0 && running_) {
565                fprintf(stderr, "vic: mme callback: done bit = 0\n");
566        }
567
568        /* Check for wraparound */
569        if( vh->dwTimeCaptured < last_grab_ )
570                last_grab_ = last_grab_ - sizeof(vh->dwTimeCaptured)*8;
571
572        /*
573        ** See if we want to keep this frame
574        ** The capture overhead is low enough that we just capture them all
575        ** then throw away the ones we don't want
576        */
577        if(vh->dwTimeCaptured - last_grab_ > delay_ ) {
578                last_grab_ = vh->dwTimeCaptured;
579                int length = vh->dwBytesUsed;
580                u_char* p = (u_char*)vh->lpData;
581                n = consume(p, length );
582                delay_ = (int)(tick(n)/1000);
583        }
584
585        outstanding_--;
586        wantgrab_ = 1;
587
588        return (1);
589}
590
591int MmeGrabber::grab()
592{
593    MMRESULT s;
594   
595    if(outstanding_ >= buffers_ )     
596      /*  fprintf(stderr, " skipping grab\n") */ ;
597    else {
598        /* fprintf(stderr, " grab - outstanding = %d ",outstanding_); */
599        /* tfm - add multibuffer code here */
600        if(s = videoStreamAddBuffer(handle_, vh_, sizeof(*vh_)))
601          (void)mme_error(s, "couldn't queue mme buffer");
602        else
603          outstanding_++;
604    }
605    return TRUE;
606}
607
608void MmeGrabber::dispatch(int mask)
609{
610    /*    fprintf(stderr, "vic: Called MmeGrabber::dispatch\n"); */
611    while (mmeCheckForCallbacks())
612      mmeProcessCallbacks();
613    if (wantgrab_ && running_ ) {
614        wantgrab_ = 0;
615        mmeMaster->grab();
616    }
617}
618
619
620
621
622
623/***********************************************************************/
624
625MmeJpegGrabber::MmeJpegGrabber() : q_(80)
626{
627    /* fprintf(stderr, "vic: Called MmeJpegGrabber constructor\n"); */
628
629}
630
631MmeJpegGrabber::~MmeJpegGrabber()
632{
633    /* fprintf(stderr, "vic: Called MmeJpegGrabber destructor\n"); */
634
635}
636
637int MmeJpegGrabber::command(int argc, const char*const* argv)
638{
639    /* fprintf(stderr, "vic: Called MmeJpegGrabber::command\n"); */
640        if (argc == 3) {
641            /* fprintf(stderr, "vic: Called MmeGrabber::command with %s %s\n",
642                    argv[1],argv[2]); */
643                if (strcmp(argv[1], "q") == 0) {
644                        /* assume value is in range */
645                        nq_ = atoi(argv[2]);
646                        if (nq_ != q_) {
647                            q_ = nq_;
648                            MMRESULT s = videoSetQuality(handle_,
649                                                         10000 * q_ / 100 );
650                            (void)mme_error(s, "couldn't set quality\n");
651                        }
652
653                        return (TCL_OK);
654                }
655        }
656        return (MmeGrabber::command(argc, argv));
657}
658
659int MmeJpegGrabber::consume(const u_char* p, int length)
660{
661/*    fprintf(stderr, "vic: Called MmeJpegGrabber::consume()\n"); */
662        /*
663         * We should get a better timestamp XXX
664         */
665        JpegFrame f(media_ts(), (u_char*)p, length, q_, 0, inw_, inh_);
666        return (target_->consume(&f));
667}
668
669void MmeJpegGrabber::SetComp()
670{
671    /* fprintf(stderr,"vic: Called MmeJpegGrabber::SetComp()\n"); */
672
673
674    inw_ = NTSC_WIDTH / x_decimate_;
675    inh_ = NTSC_HEIGHT / y_decimate_;
676
677    if( bmh == 0 )
678      fprintf(stderr,"Bitmap infoheader pointer is null\n");
679    memset(bmh, 0, sizeof(*bmh));
680    bmh->b.bmi.biSize = sizeof(*bmh);
681    bmh->b.bmi.biWidth = inw_;
682    bmh->b.bmi.biHeight = inh_;
683    bmh->b.bmi.biPlanes = 1;
684    bmh->b.bmi.biBitCount = 24;
685    bmh->b.bmi.biCompression = MJPG_DIB;
686    bmh->b.biExtDataOffset = sizeof(bmh->b);
687    bmh->jpeg.JPEGSize = sizeof(bmh->jpeg);
688    bmh->jpeg.JPEGProcess = JPEG_PROCESS_BASELINE;
689    bmh->jpeg.JPEGColorSpaceID = JPEG_YCbCr;
690    bmh->jpeg.JPEGBitsPerSample = 8;
691    bmh->jpeg.JPEGHSubSampling = 2;
692    bmh->jpeg.JPEGVSubSampling = 1;
693
694}
695
696
697/***********************************************************************/
698
699
700
701MmeYuvGrabber::MmeYuvGrabber()
702{
703    /* fprintf(stderr, "vic: Called MmeYuvGrabber constructor\n"); */
704}
705
706int MmeYuvGrabber::consume(const u_char* buffer, int length)
707{
708        suppress(buffer, frame_);
709        saveblks(buffer);
710        YuvFrame f(media_ts(), frame_, crvec_, outw_, outh_);
711        return (target_->consume(&f));
712}
713
714/*
715 * define these for REPLENISH macro used below
716 */
717#define DIFF4(in, frm, v) \
718        v += (in)[0] - (frm)[0]; \
719        v += (in)[2] - (frm)[1]; \
720        v += (in)[4] - (frm)[2]; \
721        v += (in)[6] - (frm)[3];
722
723#define DIFFLINE(in, frm, left, center, right) \
724        DIFF4(in, frm, left); \
725        DIFF4(in + 1*8, frm + 1*4, center); \
726        DIFF4(in + 2*8, frm + 2*4, center); \
727        DIFF4(in + 3*8, frm + 3*4, right); \
728        if (right < 0) \
729                right = -right; \
730        if (left < 0) \
731                left = -left; \
732        if (center < 0) \
733                center = -center;
734
735void MmeYuvGrabber::suppress(const u_char* devbuf, const u_char* lumbuf)
736{
737        const u_char* start = frame_ + 16 * vstart_ * outw_ + 16 * hstart_;
738        REPLENISH(devbuf, start, inw_ << 1, 2,
739                  hstart_, hstop_, vstart_, vstop_);
740}
741
742
743void MmeYuvGrabber::SetComp()
744{
745    /* fprintf(stderr,"vic: Called MmeYUVGrabber::SetComp()\n"); */
746
747    int w = NTSC_WIDTH / x_decimate_;
748    int h = NTSC_HEIGHT / y_decimate_;
749    if (w != inw_ || h != inh_) {
750        setsize(w, h);
751    }
752
753    if( bmh == 0 )
754      fprintf(stderr,"Bitmap infoheader pointer is null\n"); /* Uh oh! */
755    else {
756        memset(bmh, 0, sizeof(*bmh));
757        bmh->b.bmi.biSize = sizeof(BITMAPINFOHEADER);
758        bmh->b.bmi.biWidth = inw_;
759        bmh->b.bmi.biHeight = inh_;
760        bmh->b.bmi.biPlanes = 1;
761        bmh->b.bmi.biBitCount = 16;
762        bmh->b.bmi.biCompression = BICOMP_DECYUVDIB;
763    }
764}
765
766
767/***********************************************************************/
768
769
770
771/*
772** Take YUV 4:2:2 packed data and unpack it into YUV 4:2:2 with each
773** component in a separate block of memory
774*/
775
776inline void Mme422Grabber::saveblk(const u_char* in, u_char* yp, u_char* up,
777                                  u_char* vp, int stride)
778{
779        int is = stride << 1;
780        int cs = stride >> 1;
781
782        for (int i = 16; --i >= 0; ) {
783                /*
784                 * Each iteration of this loop grabs 16 Ys & 8 U/Vs.
785                 */
786                register u_int y0, y1, u, v;
787
788                u  = in[1] | in[5]  << 8 | in[9]  << 16 | in[13] << 24;
789                v  = in[3] | in[7]  << 8 | in[11] << 16 | in[15] << 24;
790                y0 = in[0] | in[2]  << 8 | in[4]  << 16 | in[6]  << 24;
791                y1 = in[8] | in[10] << 8 | in[12] << 16 | in[14] << 24;
792
793                ((u_int*)yp)[0] = y0;
794                ((u_int*)yp)[1] = y1;
795                *(u_int*)up = u;
796                *(u_int*)vp = v;
797
798                u  = in[16+1] | in[16+5]  << 8 | in[16+9]  << 16 | in[16+13] << 24;
799                v  = in[16+3] | in[16+7]  << 8 | in[16+11] << 16 | in[16+15] << 24;
800                y0 = in[16+0] | in[16+2]  << 8 | in[16+4]  << 16 | in[16+6] << 24;
801                y1 = in[16+8] | in[16+10] << 8 | in[16+12] << 16 | in[16+14] << 24;
802
803                ((u_int*)yp)[2] = y0;
804                ((u_int*)yp)[3] = y1;
805                ((u_int*)up)[1] = u;
806                ((u_int*)vp)[1] = v;
807
808                in += is;
809                yp += stride;
810                up += cs;
811                vp += cs;
812        }
813}
814
815void Mme422Grabber::saveblks(const u_char* in)
816{
817        u_char* crv = crvec_;
818        u_char* lum = frame_;
819        int off = framesize_;
820        u_char* chm = lum + off;
821        off >>= 1;
822        int stride = 15 * inw_;
823        for (int y = 0; y < blkh_; ++y) {
824                for (int x = 0; x < blkw_; ++x) {
825                        int s = *crv++;
826                        if ((s & CR_SEND) != 0)
827                                saveblk(in, lum, chm, chm + off, outw_);
828
829                        in += 32;
830                        lum += 16;
831                        chm += 8;
832                }
833                lum += stride;
834                chm += stride >> 1;
835                in += stride << 1;
836        }
837}
838
839void Mme422Grabber::setsize(int w, int h)
840{
841        set_size_422(w, h);
842}
843
844/***********************************************************************/
845
846void MmeCIFGrabber::setsize(int w, int h)
847{
848        set_size_cif(w, h);
849}
850
851/*
852** Take YUV 4:2:2 packed data and unpack it into YUV 4:1:1 with each
853** components in a separate block of memory. 
854**
855** NB: The chroma is subsampled with no prefiltering.  The samples are
856**     cosited with the first of the pair of scan lines rather than
857**     being positioned between them as specified for true CIF
858*/
859
860inline void MmeCIFGrabber::saveblk(const u_char* in, u_char* yp, u_char* up,
861                                  u_char* vp, int stride, int is)
862{
863        int cs = stride >> 1;
864
865        for (int i = 8; --i >= 0; ) {
866                /*
867                 * Each iteration of this loop grabs 16 Ys & 8 U/Vs.
868                 */
869                register u_int y0, y1, u, v;
870
871                u  = in[1] | in[5]  << 8 | in[9]  << 16 | in[13] << 24;
872                v  = in[3] | in[7]  << 8 | in[11] << 16 | in[15] << 24;
873                y0 = in[0] | in[2]  << 8 | in[4]  << 16 | in[6] << 24;
874                y1 = in[8] | in[10] << 8 | in[12] << 16 | in[14] << 24;
875
876                ((u_int*)yp)[0] = y0;
877                ((u_int*)yp)[1] = y1;
878                *(u_int*)up = u;
879                *(u_int*)vp = v;
880
881                u  = in[16+1] | in[16+5]  << 8 | in[16+9]  << 16 | in[16+13] << 24;
882                v  = in[16+3] | in[16+7]  << 8 | in[16+11] << 16 | in[16+15] << 24;
883                y0 = in[16+0] | in[16+2]  << 8 | in[16+4]  << 16 | in[16+6] << 24;
884                y1 = in[16+8] | in[16+10] << 8 | in[16+12] << 16 | in[16+14] << 24;
885
886                ((u_int*)yp)[2] = y0;
887                ((u_int*)yp)[3] = y1;
888                ((u_int*)up)[1] = u;
889                ((u_int*)vp)[1] = v;
890
891                in += is;
892                yp += stride;
893                up += cs;
894                vp += cs;
895
896                /* do the 2nd (y only instead of yuv) line */
897                y0 = in[0] | in[2]  << 8 | in[4]  << 16 | in[6] << 24;
898                y1 = in[8] | in[10] << 8 | in[12] << 16 | in[14] << 24;
899
900                ((u_int*)yp)[0] = y0;
901                ((u_int*)yp)[1] = y1;
902
903                y0 = in[16+0] | in[16+2]  << 8 | in[16+4]  << 16 | in[16+6] << 24;
904                y1 = in[16+8] | in[16+10] << 8 | in[16+12] << 16 | in[16+14] << 24;
905
906                ((u_int*)yp)[2] = y0;
907                ((u_int*)yp)[3] = y1;
908
909                in += is;
910                yp += stride;
911        }
912}
913
914void MmeCIFGrabber::saveblks(const u_char* in)
915{
916        int is = 2 * inw_;
917        u_char* crv = crvec_;
918        u_char* lum = frame_;
919        u_char* chm = frame_ + framesize_;
920        u_int off = framesize_ >> 2;
921
922        crv += vstart_ * blkw_ + hstart_;
923        lum += vstart_ * outw_ * 16 + hstart_ * 16;
924        chm += vstart_ * (outw_ >> 1) * 8 + hstart_ * 8;
925
926        int skip = hstart_ + (blkw_ - hstop_);
927
928        for (int y = vstart_; y < vstop_; ++y) {
929                const u_char* nin = in;
930                for (int x = hstart_; x < hstop_; ++x) {
931                        int s = *crv++;
932                        if ((s & CR_SEND) != 0)
933                                saveblk(in, lum, chm, chm + off, outw_, is);
934
935                        in += 32;
936                        lum += 16;
937                        chm += 8;
938                }
939                crv += skip;
940                lum += 15 * outw_ + skip * 16;
941                chm += 7 * (outw_ >> 1) + skip * 8;
942                in = nin + 16 * is;
943        }
944}
945
946/***********************************************************************/
947
948
949void Mme411Grabber::setsize(int w, int h)
950{
951        set_size_411(w, h);
952}
953
954/***********************************************************************/
Note: See TracBrowser for help on using the browser.