root/vic/branches/cc/video/grabber-macosx.cpp @ 4703

Revision 4703, 21.4 KB (checked in by soohyunc, 4 years ago)

this commit reflects Revision 4701 from the mpeg4 branch.

copied comments follows:
Removed MacOS X 10.3 workaround code originally from Aqua AG vic which I
initially thought was a Quicktime Pthread related issue and wrote so in the
comments.

It was actually to do with the framework initialization not being called.
Framework initialization is not required and shouldn't be used with MacOS X
10.3.9 and later.

Line 
1/*
2 * grabber-macosx.cpp --
3 *
4 * Video capture support for Mac OS X.
5 *
6 * Imported from OpenMash vic. Updated to use SGGetChannelDeviceList to list
7 * all of the available SequenceGrabber video capture devices and corresponding
8 * inputs, instead of using just the default capture device and input.
9 * - Douglas Kosovic <douglask@itee.uq.edu.au>
10 *
11 * Updated to work with the iSight camera (and others) using the
12 * SequenceGrabber API - Bruce Williams <netmaster_bruce@mac.com>
13 *
14 * It would be nicer to do the image conversion by calling DecompressImage with
15 * a GWorld as that will scale and resample the image instead of cropping which
16 * the YUV conversion functions do.
17 *
18 * Copyright (c) 2000-2002 The Regents of the University of California.
19 * All rights reserved.
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 *
24 * A. Redistributions of source code must retain the above copyright notice,
25 *    this list of conditions and the following disclaimer.
26 * B. Redistributions in binary form must reproduce the above copyright notice,
27 *    this list of conditions and the following disclaimer in the documentation
28 *    and/or other materials provided with the distribution.
29 * C. Neither the names of the copyright holders nor the names of its
30 *    contributors may be used to endorse or promote products derived from this
31 *    software without specific prior written permission.
32 *
33 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
34 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
35 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
36 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
37 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
38 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
39 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
40 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
41 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43 * POSSIBILITY OF SUCH DAMAGE.
44 */
45
46/* QuickTime is not available to 64-bit clients */
47#if !__LP64__
48
49#include <QuickTime/QuickTime.h>
50#include <Carbon/Carbon.h>
51#include <stdio.h>
52
53#if !defined(MAC_TCL) && !defined(MAC_OSX_TK)
54#define Cursor XCursor
55#endif
56
57#include "grabber.h"
58#include "vic_tcl.h"
59#include "device-input.h"
60#include "module.h"
61#include "bsd-endian.h"
62
63/***************************************************************************/
64// FIXME: This is definitely *not* the place to define video sizes
65#define PAL                  0
66#define NTSC                 1
67
68// CIF
69#define CIF_WIDTH          352
70#define CIF_HEIGHT         288
71// QCIF
72#define QCIF_WIDTH         176
73#define QCIF_HEIGHT        144
74// Square-pixel CCIR-601 format, digitally-encoded NTSC resolution
75#define SP601_NTSC_WIDTH   640
76#define SP601_NTSC_HEIGHT  480
77// Square-pixel CCIR-601 format, digitally-encoded PAL resolution
78#define SP601_PAL_WIDTH    768
79#define SP601_PAL_HEIGHT   576
80// Square-pixel SIF format, digitally-encoded NTSC resolution
81#define SPSIF_NTSC_WIDTH   320
82#define SPSIF_NTSC_HEIGHT  240
83// Square-pixel SIF format, digitally-encoded PAL resolution
84#define SPSIF_PAL_WIDTH    384
85#define SPSIF_PAL_HEIGHT   288
86
87// Color subsampling options.
88#define CF_422 422
89#define CF_411 411
90#define CF_CIF 4112
91
92typedef struct  {
93        GWorldPtr gWorld;
94        ImageSequence decomSeq;
95} SGDataProcRefCon;
96
97#define BailErr(x) {err = x; if(err != noErr) goto bail;}
98
99/***************************************************************************/
100// The video capture class.
101class MacOSXGrabber : public Grabber {
102public:
103    // Constructor.
104    MacOSXGrabber(const char* format, const char* dev);
105       
106    // Destructor.
107    virtual ~MacOSXGrabber();
108       
109    // Minimum necessary functions.
110    virtual void start();
111    virtual void stop();
112    virtual int grab();
113       
114    // Overridden functions.
115    virtual int command(int argc, const char*const* argv);
116       
117protected:
118    // sequence grabber support requires a callback function
119    static OSErr seqGrabberDataProc(SGChannel, Ptr, long, long *, long, TimeValue, short, long);
120
121    // Supplemental functions.
122    void format();
123    int setport(const char *port);
124    int capture();
125    int setupDecom(void);
126       
127    // YUV conversion functions.
128    void packedYUYV422_to_planarYUYV422(char *dest, char *src);
129    void packedYUYV422_to_planarYUYV411(char *dest, char *src);
130       
131    // The frame information.
132    int decimate_;
133    int width_, height_;
134       
135    int imageSize;
136   
137    // True if sequence grabbing is possible.
138    Boolean quicktime_;
139   
140    // sequence grabber
141    SeqGrabComponent    seqGrab;
142    SGChannel           sgchanVideo;
143       
144    /*
145     * A graphics world would be a nicer way to convert and resample the image.
146     */
147    ImageDescriptionHandle desc_;
148    GWorldPtr gWorld_;
149    Rect frameRect_;
150       
151    SGDataProcRefCon *sgDataProcRefCon;
152       
153    // The capture format.
154    int format_;
155
156    // Name of the video capture device
157    const char *dev_;
158
159    // the capture port
160    char port_[64];
161
162    // Video input standard - ntscIn, palIn or secamIn
163    short input_standard_;
164       
165    // Use SequenceGrabber config dialog box
166    bool useconfig_;
167       
168    // A simple exception handler class.
169    class Exception {
170        public:
171        Exception(char* s) {
172            string = s;
173        }
174               
175        char* string;
176    };
177};
178
179MacOSXGrabber::MacOSXGrabber(const char* format, const char* dev) {
180    OSErr err = noErr;
181    quicktime_ = true;
182    decimate_ = 0;
183    gWorld_ = NULL;
184    seqGrab = NULL;
185    dev_ = dev;
186    input_standard_ = ntscIn;
187    port_[0] = 0;
188    useconfig_ = false;
189
190     // allocate prezeroed nonrelocatable block of memory
191        sgDataProcRefCon = (SGDataProcRefCon *)NewPtrClear(sizeof(SGDataProcRefCon));
192
193    InitCursor();
194    EnterMovies();
195       
196    try {
197                // Remember the format.
198                if (strcmp(format, "422") == 0) format_ = CF_422;
199                else if (strcmp(format, "411") == 0) format_ = CF_411;
200                else if (strcmp(format, "cif") == 0) format_ = CF_CIF;
201                else throw Exception("Unrecognized format");
202    } catch (Exception e) {
203                quicktime_ = false;
204                fprintf(stderr, "QuickTime error[%d]: %s\n", err, e.string);
205    }
206}
207
208MacOSXGrabber::~MacOSXGrabber() {
209    /*
210     * Graphics worlds must be disposed of if used.
211     */
212    // Dipose of the GWorld.
213    if (gWorld_ != NULL) DisposeGWorld(gWorld_);
214       
215    // Close the video digitizer component.
216    CloseComponent(seqGrab);
217
218        // Dispose of nonrelocatable block of memory
219        if (sgDataProcRefCon != NULL) DisposePtr((char *)sgDataProcRefCon);
220}
221
222void MacOSXGrabber::start() {
223    OSErr       err = noErr;
224       
225    // Don't do anything if QuickTime failed.
226    if (!quicktime_) return;
227       
228    // start the sequencer
229    err = SGStartRecord(seqGrab);
230       
231    // Start capturing.
232    Grabber::start();
233}
234
235void MacOSXGrabber::stop() {
236    // Don't do anything if QuickTime failed.
237    if (!quicktime_) return;
238       
239    // stop the sequencer
240    SGStop(seqGrab);
241       
242    // Stop capturing.
243    Grabber::stop();
244}
245
246int MacOSXGrabber::grab() {
247    if (sgDataProcRefCon->decomSeq == 0) {
248                if (setupDecom()) {
249                        return 0;
250                }
251    }
252    if (capture() == 0) return 0;
253    suppress(frame_);
254    saveblks(frame_);
255    YuvFrame f(media_ts(), frame_, crvec_, outw_, outh_, format_);
256
257    if(target_)
258       return(target_->consume(&f));
259    return 0;
260}
261
262int MacOSXGrabber::capture() {
263    OSErr err = noErr;
264    Ptr theData;
265    long dataSize;
266
267        /*
268         * Needed if decompressing to a graphics world.
269         */
270    GWorldPtr currentGWorld;
271    GDHandle currentGDevice;
272
273    try {
274                /*
275                 * this does the work of grabbing from the camera
276                 */
277        err = SGIdle(seqGrab);
278
279        // Save the current graphics port.
280        GetGWorld(&currentGWorld, &currentGDevice);
281        SetGWorld(gWorld_, NULL);
282
283                theData = GetPixBaseAddr(GetGWorldPixMap(gWorld_));
284                dataSize = imageSize;
285
286        // Restore the graphics port.
287        SetGWorld(currentGWorld, currentGDevice);
288       
289        // Copy the frame.
290                /*
291                 * i'd like to be able to use Quicktime to do the colour space
292                 * conversions here, or remove the need for them totally!
293                 */
294        switch (format_) {
295            case CF_422:
296                packedYUYV422_to_planarYUYV422((char*)frame_, theData);
297                break;
298            case CF_411:
299            case CF_CIF:
300                packedYUYV422_to_planarYUYV411((char*)frame_, theData);
301                break;
302        }
303
304    } catch (Exception e) {
305        fprintf(stderr, "QuickTime error[%d]: %s\n", err, e.string);
306        return 0;
307    }
308
309    // Return success.
310    return 1;
311}
312
313void MacOSXGrabber::format() {
314    OSErr err = noErr;
315   
316    // Set the image size.
317    switch (decimate_) {
318                case 1: // full-sized
319                        width_ = SP601_NTSC_WIDTH;
320                        height_ = SP601_NTSC_HEIGHT;
321                        break;
322                case 2: // CIF-sized
323                        width_ = CIF_WIDTH;
324                        height_ = CIF_HEIGHT;
325                        break;
326                case 4: // QCIF - may not work
327                        width_ = QCIF_WIDTH;
328                        height_ = QCIF_HEIGHT;
329                        break;
330    }
331    switch (format_) {
332                case CF_422:
333                        set_size_422(width_, height_);
334                        break;
335                case CF_411:
336                        set_size_411(width_, height_);
337                        break;
338                case CF_CIF:
339                        set_size_cif(width_, height_);
340                        break;
341    }
342       
343    try {
344        // Set the frame rect.
345        SetRect(&frameRect_, 0, 0, width_, height_);
346
347        if (gWorld_ == NULL) {
348            // Create or update an offscreen GWorld for the frame pixel map.
349            err = QTNewGWorld(&gWorld_, kYUVSPixelFormat, &frameRect_, 0, NULL, 0);
350            if (err != noErr) throw Exception("QTNewGWorld");
351                        sgDataProcRefCon->gWorld = gWorld_;
352            if (!LockPixels(GetGWorldPixMap(gWorld_))) throw Exception("LockPixels");
353                       
354            /*
355             * ref: MakeSequenceGrabber()
356                         * need better error checking here
357                         */ 
358                        seqGrab = OpenDefaultComponent(SeqGrabComponentType, 0);
359                        if (seqGrab != NULL)
360                                err = SGInitialize(seqGrab);
361            if (err == noErr)
362                                err = SGSetGWorld(seqGrab, NULL, NULL);
363                        if (err == noErr)
364                                err = SGSetDataRef(seqGrab, 0, 0, seqGrabDontMakeMovie);
365                       
366                        /* ref: MakeSequenceGrabChannel */
367                        err = SGNewChannel(seqGrab, VideoMediaType, &sgchanVideo);
368                        if (err == noErr) {
369                                Str63 devPStr;
370                                c2pstrcpy(devPStr, dev_);
371
372                                SGSetChannelDevice(sgchanVideo, (StringPtr)&devPStr);
373
374                                setport(port_);
375
376                                VideoDigitizerComponent vdigComponent = SGGetVideoDigitizerComponent(sgchanVideo);
377                                DigitizerInfo digitizerInfo;
378                                err = VDGetDigitizerInfo(vdigComponent, &digitizerInfo);
379                                if (err == noErr) {
380                                        if ((digitizerInfo.inputCapabilityFlags & digiInDoesNTSC) && (input_standard_ == ntscIn)) {
381                                                err = VDSetInputStandard(vdigComponent, ntscIn);
382                                        } else if ((digitizerInfo.inputCapabilityFlags & digiInDoesPAL) && (input_standard_ == palIn)) {
383                                                err = VDSetInputStandard(vdigComponent, palIn);
384                                        } else if ((digitizerInfo.inputCapabilityFlags & digiInDoesSECAM) && (input_standard_ == secamIn)) {
385                                                err = VDSetInputStandard(vdigComponent, secamIn);
386                                        }
387                                }
388
389                /* set sg to gworld */
390                err = SGSetGWorld(seqGrab, gWorld_, GetMainDevice());
391                               
392                                err = SGSetChannelBounds(sgchanVideo, (const Rect *)&frameRect_);
393                               
394                                if (err == noErr)
395                                        err = SGSetChannelUsage(sgchanVideo, seqGrabRecord);
396                                if (err != noErr) {
397                                        SGDisposeChannel(seqGrab, sgchanVideo);
398                                        sgchanVideo = NULL;
399                                }
400                        }
401                        err = SGSetDataProc(seqGrab, NewSGDataUPP(&seqGrabberDataProc), (long)sgDataProcRefCon);
402                        err = SGPrepare(seqGrab, false, true);
403                       
404        } else {
405                        fprintf(stderr, "      format() - reformat not implemented!\n");
406                        //            UnlockPixels(GetGWorldPixMap(gWorld_));
407                        //            UpdateGWorld(&gWorld_, kYUVUPixelFormat, &frameRect_, 0, NULL, 0);
408                        //            if (!LockPixels(GetGWorldPixMap(gWorld_))) throw Exception("LockPixels");
409        }
410    } catch (Exception e) {
411        fprintf(stderr, "QuickTime error[%d]: %s\n", err, e.string);
412    }
413    // Allocate the reference buffer.
414    allocref();
415}
416
417int MacOSXGrabber::setport(const char *port) {
418        OSErr err = noErr;
419        int inputNumber = 0;
420       
421        if (strcmp(port_, port) == 0) {
422                return 0;
423        }
424
425        SGDeviceList sgdeviceList;
426        err = SGGetChannelDeviceList(sgchanVideo, sgDeviceListIncludeInputs, &sgdeviceList);
427        if (err != noErr) {
428                return TCL_ERROR;
429        }
430        char port_str[64];
431        int selectedIndex = (*sgdeviceList)->selectedIndex;
432        for (int i = 0; i < (*(((*sgdeviceList)->entry[selectedIndex]).inputs))->count; i++) {
433                p2cstrcpy(port_str, (*(((*sgdeviceList)->entry[selectedIndex]).inputs))->entry[i].name);
434                if (strcmp(port, port_str) == 0) {
435                        inputNumber = i;
436                }
437        }
438        SGDisposeDeviceList(seqGrab, sgdeviceList);
439
440        if (running_) {
441                stop();
442        }
443
444        err = SGSetChannelDeviceInput(sgchanVideo, inputNumber);
445        if (err != noErr) {
446                strcpy((char*)port, port_);
447                return TCL_ERROR;
448        }
449}
450
451int MacOSXGrabber::command(int argc, const char*const* argv) {
452    // fprintf(stderr,"### MacOSXGrabber::command : argv[1] = %s\n", argv[1]);
453    if (argc == 3) {
454                if (strcmp(argv[1], "decimate") == 0) {
455                        decimate_ = atoi(argv[2]);
456                        if (running_) {
457                                stop();
458                        }
459                        format();
460                        start();
461                        return(TCL_OK);
462
463                } else if (strcmp(argv[1], "port") == 0) {
464                        if (seqGrab == NULL) {
465                                strcpy((char *)argv[2], port_);
466                        } else {
467                                setport(argv[2]);
468                                start();
469                                return(TCL_OK);
470                        }
471        } else if (strcmp(argv[1], "type") == 0) {
472                        if (strcmp(argv[2], "pal") == 0)
473                                input_standard_ = palIn;
474                        else if (strcmp(argv[2], "secam") == 0)
475                                input_standard_ = secamIn;
476                        else
477                                input_standard_ = ntscIn;
478
479                        return(TCL_OK);
480
481        } else if (strcmp(argv[1], "useconfig") == 0) {
482                        if (strcmp(argv[2], "1") == 0) useconfig_ = true;
483                        if (strcmp(argv[2], "0") == 0) useconfig_ = false;
484
485        }  else if (strcmp(argv[1], "send") == 0) {
486                        if (useconfig_ && running_ == 0) {
487                                Component *panelListPtr = NULL;
488                                UInt8 numberOfPanels = 0;
489
490                                ComponentDescription cd = { SeqGrabPanelType, VideoMediaType, 0, 0, 0 };
491                                Component        c = 0;
492                                Component *cPtr = NULL;
493
494                                // set up the settings panel list removing the "Compression" and "Source" panels
495                                numberOfPanels = CountComponents(&cd);
496                                if (numberOfPanels == 0)
497                                        return TCL_ERROR;
498
499                                panelListPtr = (Component *)NewPtr(sizeof(Component) * (numberOfPanels + 1));
500                                if (MemError() || panelListPtr == NULL)
501                                        return TCL_ERROR;
502
503                                cPtr = panelListPtr;
504                                numberOfPanels = 0;
505                                char panel_name[255];
506                                do {
507                                        ComponentDescription compInfo;
508                                        c = FindNextComponent(c, &cd);
509                                        if (c) {
510                                                Handle hName = NewHandle(0);
511                                                if (MemError() || hName == NULL)
512                                                        return TCL_ERROR;
513                                                GetComponentInfo(c, &compInfo, hName, NULL, NULL);
514                                                p2cstrcpy(panel_name, (unsigned char*)(*hName));
515                                                if (strcmp(panel_name, "Compression") != 0 && strcmp(panel_name, "Source") != 0) {
516                                                        *cPtr++ = c;
517                                                        numberOfPanels++;
518                                                }
519                                                DisposeHandle(hName);
520                                        }
521                                } while (c);
522
523                                SGSettingsDialog(seqGrab, sgchanVideo, numberOfPanels, panelListPtr, 0, NULL, 0);
524                        }
525        }
526
527    } else if (argc == 2) {
528                if (strcmp(argv[1], "decimate") == 0) {
529                        Tcl& tcl = Tcl::instance();
530                        tcl.resultf("%d", decimate_);
531                        return (TCL_OK);
532                }
533    }
534    return Grabber::command(argc, argv);
535}
536
537int MacOSXGrabber::setupDecom(void) {
538        ComponentResult err = noErr;
539        Rect sourceRect = { 0, 0 };
540        MatrixRecord scaleMatrix;
541        ImageDescriptionHandle imageDesc = (ImageDescriptionHandle)NewHandle(0);
542       
543        err = SGGetChannelSampleDescription(sgchanVideo, (Handle)imageDesc);
544        BailErr(err);
545       
546        sourceRect.right = (**imageDesc).width;
547        sourceRect.bottom = (**imageDesc).height;
548        RectMatrix(&scaleMatrix, &sourceRect, &frameRect_);
549       
550        err = DecompressSequenceBegin(&(sgDataProcRefCon->decomSeq),
551                                                                  imageDesc,
552                                                                  sgDataProcRefCon->gWorld,
553                                                                  NULL,
554                                                                  NULL,
555                                                                  &scaleMatrix,
556                                                                  srcCopy,
557                                                                  NULL,
558                                                                  0,
559                                                                  codecNormalQuality,
560                                                                  bestSpeedCodec);
561        BailErr(err);
562       
563        imageSize = ((*imageDesc)->width * (*imageDesc)->height);
564       
565        DisposeHandle ((Handle)imageDesc);
566        imageDesc = NULL;
567       
568bail:
569                if (imageDesc)
570                        DisposeHandle((Handle)imageDesc);
571        return(err);
572}
573
574/*
575 * video sequence data proc
576 */
577OSErr MacOSXGrabber::seqGrabberDataProc(SGChannel c, Ptr p, long len, long *offset, long chRefCon, TimeValue time, short writeType, long refCon) {
578       
579#pragma unused (c, offset, chRefCon, time, writeType)
580       
581        ComponentResult err = noErr;
582        CodecFlags ignore;
583
584        SGDataProcRefCon *sgDataProcRefCon = (SGDataProcRefCon *)refCon;
585
586        if (!sgDataProcRefCon->gWorld) return(err);
587        err = DecompressSequenceFrameS(sgDataProcRefCon->decomSeq,
588                                                                   p,
589                                                                   len,
590                                                                   0,
591                                                                   &ignore,
592                                                                   NULL);
593        return(err);
594}
595
596/***************************************************************************/
597// The hybrid class providing Tcl with access to the video capture device.
598class MacOSXDevice : public InputDevice {
599public:
600    MacOSXDevice(const char* device, char *attr);
601    virtual int command(int argc, const char*const* argv);
602};
603
604MacOSXDevice::MacOSXDevice(const char* device, char *attr) : InputDevice(device) {
605        attributes_ = attr;
606    fprintf(stderr,"OSX Capture:  ==> %s\n", attr);
607}
608
609int MacOSXDevice::command(int argc, const char*const* argv)
610{
611        //fprintf(stderr,"### MacOSXDevice::command : argv[1] = %s\n", argv[1]);
612    Tcl& tcl = Tcl::instance();
613    if (argc == 3) {
614                if (strcmp(argv[1], "open") == 0) {
615                        TclObject* o = 0;
616                        o = new MacOSXGrabber(argv[2], nickname_);
617                        if (o != 0)
618                                tcl.result(o->name());
619                        return(TCL_OK);
620                }
621    }
622    return(InputDevice::command(argc, argv));
623}
624
625
626class MacOSXScanner {
627public:
628    MacOSXScanner();
629};
630
631// Instantiate the video capture device.
632static MacOSXScanner find_capture_devices;
633
634MacOSXScanner::MacOSXScanner()
635{
636        char *attr;
637        SeqGrabComponent seqGrab;
638        SGChannel sgchanVideo;
639        SGDeviceList sgdeviceList;
640        OSErr err = noErr;
641       
642        char *myDev = getenv("VIC_DEVICE");
643        if (myDev != 0) {
644               
645        }
646        seqGrab = OpenDefaultComponent(SeqGrabComponentType, 0);
647        if (seqGrab != NULL)
648                err = SGInitialize(seqGrab);
649        if (err == noErr)
650                err = SGSetGWorld(seqGrab, NULL, NULL);
651        if (err == noErr)
652                err = SGSetDataRef(seqGrab, 0, 0, seqGrabDontMakeMovie);
653        err = SGNewChannel(seqGrab, VideoMediaType, &sgchanVideo);
654        if (err != noErr) {
655                // clean up on failure
656                SGDisposeChannel(seqGrab, sgchanVideo);
657                return;
658        }
659        if (err == noErr) {
660                SGGetChannelDeviceList(sgchanVideo, sgDeviceListIncludeInputs, &sgdeviceList);
661                char dev_str[64];
662                char port_str[64];
663                for (int i = 0; i < (*sgdeviceList)->count; i++) {
664                        // ignore devices that are currently unavailable
665                        p2cstrcpy(dev_str, (*sgdeviceList)->entry[i].name);
666                        if ((sgDeviceNameFlagDeviceUnavailable & (*sgdeviceList)->entry[i].flags) == 0) {
667                                attr = new char[512];
668                                strcpy(attr, "size {large small cif} format {411 422 cif} type {ntsc pal secam} port {");
669                                if ((*sgdeviceList)->entry[i].inputs != NULL) {
670                                        fprintf(stderr,"OSX Capture: \"%s\" has %i input(s)\n", dev_str, (*(((*sgdeviceList)->entry[i]).inputs))->count);
671                                        for (int j = 0; j < (*(((*sgdeviceList)->entry[i]).inputs))->count; j++) {
672                                                p2cstrcpy(port_str, (*(((*sgdeviceList)->entry[i]).inputs))->entry[j].name);
673                                                if (strchr(port_str, ' ')) {
674                                                        strcat(attr, "\"");
675                                                        strcat(attr, port_str);
676                                                        strcat(attr, "\" ");
677                                                } else {
678                                                        strcat(attr, port_str);
679                                                        strcat(attr, " ");
680                                                }
681                                        }
682                                } else {
683                                        fprintf(stderr,"OSX Capture: \"%s\" has no inputs\n", dev_str);
684                                }
685                                strcat(attr, "}");
686                               
687                                char *device = new char[strlen(dev_str) + 1];
688                                strcpy(device, dev_str);
689                                new MacOSXDevice(device, attr);
690                                //delete [] device;
691                                //delete [] attr;
692                        } else {
693                                fprintf(stderr,"OSX Capture: \"%s\" unavailable, ignoring\n", dev_str);
694                        }
695                }
696               
697        }
698       
699        SGDisposeDeviceList(seqGrab, sgdeviceList);
700        SGDisposeChannel(seqGrab, sgchanVideo);
701        CloseComponent(seqGrab);
702}
703
704
705void MacOSXGrabber::packedYUYV422_to_planarYUYV422(char *dest, char *src)
706{
707    int i;
708    char *s, *y,*u,*v;
709    unsigned int a, *srca;
710       
711    srca = (unsigned int *)src;
712       
713    i = (width_ * height_)/2;
714    s = src;
715    y = dest;
716    u = y + width_ * height_;
717    v = u + width_ * height_ / 2;
718       
719    while (--i) {
720        a = *(srca++);
721#if BYTE_ORDER == LITTLE_ENDIAN 
722        *(y++) = a & 0xff;
723        a >>= 8;
724        *(u++) = a & 0xff;
725        a >>= 8;
726        *(y++) = a & 0xff;
727        a >>= 8;
728        *(v++) = a & 0xff;
729#else
730        *(v++) = a & 0xff;
731        a >>= 8;
732        *(y++) = a & 0xff;
733        a >>= 8;
734        *(u++) = a & 0xff;
735        a >>= 8;
736        *(y++) = a & 0xff;
737#endif
738    }
739}
740
741void MacOSXGrabber::packedYUYV422_to_planarYUYV411(char *dest, char *src)
742{
743    int  a1,b;
744    char *s, *y,*u,*v;
745    unsigned int a, *srca;
746       
747    srca = (unsigned int *)src;
748       
749    s = src;
750    y = dest;
751    u = y + width_ * height_;
752    v = u + width_ * height_ / 4;
753       
754    for (a1 = height_; a1 > 0; a1 -= 2) {
755        for (b = width_; b > 0; b -= 2) {
756                        a = *(srca++);
757#if BYTE_ORDER == LITTLE_ENDIAN 
758            *(y++) = a & 0xff; a >>= 8;
759            *(u++) = a & 0xff; a >>= 8;
760            *(y++) = a & 0xff; a >>= 8;
761            *(v++) = a & 0xff;
762#else
763            *(v++) = a & 0xff; a >>= 8;
764            *(y+1) = a & 0xff; a >>= 8;
765            *(u++) = a & 0xff; a >>= 8;
766            *(y) = a;  y += 2;
767#endif
768        }
769        for (b = width_; b > 0; b -= 2) {
770                        a = *(srca++);
771#if BYTE_ORDER == LITTLE_ENDIAN 
772            *(y++) = a & 0xff; a >>= 16;
773            *(y++) = a & 0xff;
774#else
775            a >>= 8;
776            *(y+1) = a & 0xff; a >>= 16;
777            *(y) = a; y += 2;
778#endif
779        }
780    }
781}
782
783#endif // !__LP64__
Note: See TracBrowser for help on using the browser.