BigEasyVideoGrabber.c

/*
  File:         BigEasyVideoGrabber.c
  Contains:     Routines for Using the Video Digitizer.
  Written by:   David Van Brink / QT Engineering
  Copyright:    © 1991-1994 by Apple Computer, Inc., all rights reserved.
  Change History (most recent first):
  <2>       12/4/94     khs     changed the format of the file to the new look and feel
  <1>       12/18/94    dvb     1.0 Started
  To Do:
*/
 
 
// INCLUDES
#include <Memory.h>
#include <OSUtils.h>
#include "BigEasyVideoGrabber.h"
 
 
// FUNCTIONS
EasyVideoGrabber NewEasyVideoGrabber(Rect* outputSize)
/*
 * Gets the default video digitizer,
 * and returns the output size of the video image.
 */
{
    EasyVideoGrabber evg;
    ComponentResult thisError;
 
    evg = (void*)NewPtr(sizeof(EasyVideoGrabberRecord));
    if (!evg)
        goto fail;
 
    evg->sg = 0;
    evg->vc = 0;
 
    evg->sg = OpenDefaultComponent(SeqGrabComponentType, 0);
    if (!evg->sg)
        goto fail;
 
    thisError = SGInitialize(evg->sg);
    if (thisError)
        goto fail;
 
    thisError = SGNewChannel(evg->sg, VideoMediaType, &evg->vc);
    if (thisError)
        goto fail;
 
    if (outputSize)
    {
        thisError = SGGetSrcVideoBounds(evg->vc, outputSize);
        if (thisError)
            goto fail;
    }
 
    thisError = SGSetChannelUsage(evg->vc, seqGrabPreview);
    if (thisError)
        goto fail;
 
    goto goHome;
 
fail:if (evg)
    {
        if (evg->sg)
            CloseComponent(evg->sg);
        DisposePtr((void*)evg);
        evg = 0;
    }
 
goHome:return evg;
}
 
 
Boolean GrabEasyVideoGrabber(EasyVideoGrabber evg,
                             Rect* r)
/*
 * Grab a frame, and draw it in the current port, of size 'r'.
 * You can pass 'nil' for the EasyVideoGrabber, and one
 * will be allocated and disposed, while-u-wait.
 *
 * The boolean returned is 'true' iff a frame was actually captured and drawn.
 *
 * The 'while' loop is a real barnstorming technique. The "Sequence Grab"
 * component does not provide any way to know when a frame has actually
 * been grabbed. Therefore, the Sequence Grabber is simply idled for
 * a few ticks, on the _assumption_ that the video frame rate is high
 * enough that at least one frame is grabbed.
 *
 * While this may seem mildly inelegant, it, in fact, works.
 */
{
    ComponentResult thisError;
    GWorldPtr gw;
    GDHandle gd;
    Boolean localGrabber;
    unsigned long t;
    Boolean result;
 
    result = false;
 
    localGrabber = (evg == 0);
    if (localGrabber)
        evg = NewEasyVideoGrabber(nil);
 
    if (!evg)
        goto goHome;
 
    GetGWorld(&gw, &gd);
 
    thisError = SGSetGWorld(evg->sg, gw, gd);
    if (thisError)
        goto goHome;
 
    thisError = SGSetChannelBounds(evg->vc, r);
    if (thisError)
        goto goHome;
 
    thisError = SGStartPreview(evg->sg);
    if (thisError)
        goto goHome;
 
    t = TickCount() + 8;
    do
    {
        thisError = SGIdle(evg->sg);
        if (thisError)
            goto goHome;
    } while (TickCount() < t);
 
    thisError = SGStop(evg->sg);
 
    if (localGrabber)
        DisposeEasyVideoGrabber(evg);
 
    result = true;
 
goHome:;
    return result;
}
 
 
void DisposeEasyVideoGrabber(EasyVideoGrabber evg)
{
    CloseComponent(evg->sg);
    DisposePtr((void*)evg);
}