//-------------------------------------------------------------------- bool ofQuickTimeGrabber::initGrabber(int w, int h){ //--------------------------------- #ifdef OF_VIDEO_CAPTURE_QUICKTIME //--------------------------------- //---------------------------------- 1 - open the sequence grabber if( !qtInitSeqGrabber() ){ ofLogError("ofQuickTimeGrabber") << "initGrabber(): unable to initialize the seq grabber"; return false; } //---------------------------------- 2 - set the dimensions //width = w; //height = h; MacSetRect(&videoRect, 0, 0, w, h); //---------------------------------- 3 - buffer allocation // Create a buffer big enough to hold the video data, // make sure the pointer is 32-byte aligned. // also the rgb image that people will grab offscreenGWorldPixels = (unsigned char*)malloc(4 * w * h + 32); pixels.allocate(w, h, OF_IMAGE_COLOR); #if defined(TARGET_OSX) && defined(__BIG_ENDIAN__) QTNewGWorldFromPtr (&(videogworld), k32ARGBPixelFormat, &(videoRect), NULL, NULL, 0, (offscreenGWorldPixels), 4 * w); #else QTNewGWorldFromPtr (&(videogworld), k24RGBPixelFormat, &(videoRect), NULL, NULL, 0, (pixels.getPixels()), 3 * w); #endif LockPixels(GetGWorldPixMap(videogworld)); SetGWorld (videogworld, NULL); SGSetGWorld(gSeqGrabber, videogworld, nil); //---------------------------------- 4 - device selection bool didWeChooseADevice = bChooseDevice; bool deviceIsSelected = false; //if we have a device selected then try first to setup //that device if(didWeChooseADevice){ deviceIsSelected = qtSelectDevice(deviceID, true); if(!deviceIsSelected && bVerbose) ofLogError("ofQuickTimeGrabber") << "initGrabber(): unable to open device[" << deviceID << "], will attempt other devices"; } //if we couldn't select our required device //or we aren't specifiying a device to setup //then lets try to setup ANY device! if(deviceIsSelected == false){ //lets list available devices listDevices(); setDeviceID(0); deviceIsSelected = qtSelectDevice(deviceID, false); } //if we still haven't been able to setup a device //we should error and stop! if( deviceIsSelected == false){ goto bail; } //---------------------------------- 5 - final initialization steps OSStatus err; err = SGSetChannelUsage(gVideoChannel,seqGrabPreview); if ( err != noErr ) goto bail; //----------------- callback method for notifying new frame err = SGSetChannelRefCon(gVideoChannel, (long)&bHavePixelsChanged ); if(!err) { VideoBottles vb; /* get the current bottlenecks */ vb.procCount = 9; err = SGGetVideoBottlenecks(gVideoChannel, &vb); if (!err) { myGrabCompleteProc = NewSGGrabCompleteBottleUPP(frameIsGrabbedProc); vb.grabCompleteProc = myGrabCompleteProc; /* add our GrabFrameComplete function */ err = SGSetVideoBottlenecks(gVideoChannel, &vb); } } err = SGSetChannelBounds(gVideoChannel, &videoRect); if ( err != noErr ) goto bail; err = SGPrepare(gSeqGrabber, true, false); //theo swapped so preview is true and capture is false if ( err != noErr ) goto bail; err = SGStartPreview(gSeqGrabber); if ( err != noErr ) goto bail; bGrabberInited = true; loadSettings(); if( attemptFramerate >= 0 ){ err = SGSetFrameRate(gVideoChannel, IntToFixed(attemptFramerate) ); if ( err != noErr ){ ofLogError("ofQuickTimeGrabber") << "initGrabber: couldn't setting framerate to " << attemptFramerate << ": OSStatus " << err; } } ofLogNotice("ofQuickTimeGrabber") << " inited grabbed "; ofLogNotice("ofQuickTimeGrabber") << "-------------------------------------"; // we are done return true; //--------------------- (bail) something's wrong ----- bail: ofLogError("ofQuickTimeGrabber") << "***** ofQuickTimeGrabber error *****"; ofLogError("ofQuickTimeGrabber") << "------------------------------------"; //if we don't close this - it messes up the next device! if(bSgInited) qtCloseSeqGrabber(); bGrabberInited = false; return false; //--------------------------------- #else //--------------------------------- return false; //--------------------------------- #endif //--------------------------------- }
// Create the Sequence Grabber Video Channel void QuicktimeLiveImageStream::createSequenceGrabberVideoChannel() { // Check capability and setting of Sequence Grabber GDHandle origDevice; CGrafPtr origPort; // Create GWorld GetGWorld (&origPort, &origDevice); SetGWorld (m_gw, NULL); // set current graphics port to offscreen // Setup // Get a video channel ComponentResult result = SGNewChannel (m_gSeqGrabber, VideoMediaType, &m_gVideoChannel); if ((m_gVideoChannel != nil) && (result == noErr)) { result = SGInitChannel(m_gVideoChannel, m_gSeqGrabber); Rect gActiveVideoRect; // Usage if (g_s_use_sg_record) result = SGSetChannelUsage (m_gVideoChannel, seqGrabRecord | seqGrabLowLatencyCapture); else { result = SGSetChannelUsage (m_gVideoChannel, seqGrabPreview); } // result = SGSetUseScreenBuffer(m_gVideoChannel, FALSE); // Set OSG_DEBUG << "Setting up vdig from input prefs" << std::endl; result = SGSetChannelDevice ( m_gVideoChannel, m_videoDeviceIDStr); result = SGSetChannelDeviceInput( m_gVideoChannel, m_videoDeviceInputID); // result = SGSetChannelPlayFlags ( m_gVideoChannel, channelPlayFast | channelPlayHighQuality | channelPlayAllData); result = SGSetChannelPlayFlags ( m_gVideoChannel, channelPlayFast ); VideoDigitizerComponent vdig = SGGetVideoDigitizerComponent(m_gVideoChannel); VideoDigitizerError vid_err; vid_err = VDSetInputStandard (vdig, palIn); OSG_DEBUG << "Setup vdig from input prefs:" << std::endl; print_video_component_capability(vdig); result = SGVideoDigitizerChanged( m_gVideoChannel); result = SGGetSrcVideoBounds ( m_gVideoChannel, &gActiveVideoRect); result = SGSetChannelBounds ( m_gVideoChannel, &gActiveVideoRect); result = SGChangedSource (m_gSeqGrabber, m_gVideoChannel); Fixed frame_rate; result = SGGetFrameRate (m_gVideoChannel, &frame_rate); result = SGSetFrameRate (m_gVideoChannel, 100); // // Sound /* long sound_id; Str255 sound_driver_name; char* sound_driver_name_cstr; vid_err = VDGetSoundInputSource(vdig, (long)m_videoDeviceInputID, &sound_id); vid_err = VDGetSoundInputDriver(vdig, sound_driver_name); sound_driver_name_cstr = pstr_printable(sound_driver_name); OSG_DEBUG << "vdig sound driver name :" << sound_driver_name_cstr << std::endl; OSG_DEBUG << "vdig sound driver id :" << sound_id << std::endl; */ } else { OSG_FATAL << "Could not create SGNewChannel for Video Channel" << std::endl; } // Set GWorld back SetGWorld(origPort, origDevice); }
// ###################################################################### QuickTimeGrabber::Impl::Impl(const Dims& dims) : itsSeqGrab(0, &CloseComponent), itsSGChanVideo(&itsSeqGrab.it), itsDrawSeq(0), itsTimeScale(0), itsTimeBase(0), itsQueuedFrameCount(0), itsSkipFrameCount(0), itsSkipFrameCountTotal(0), itsPrevTime(0), itsFrameCount(0), itsGWorld(0), itsGotFrame(false), itsCurrentImage(), itsErrorMsg(), itsStreamStarted(false) { OSErr err; EnterMovies(); // open the default sequence grabber itsSeqGrab.it = OpenDefaultComponent(SeqGrabComponentType, 0); if (itsSeqGrab.it == NULL) LFATAL("OpenDefaultComponent() failed"); // initialize the default sequence grabber component if (noErr != (err = SGInitialize(itsSeqGrab.it))) LFATAL("SGInitialize() failed (err=%ld)", (long) err); Rect scaleRect; MacSetRect(&scaleRect, 0, 0, dims.w(), dims.h()); ASSERT(itsGWorld == 0); QTNewGWorld(&itsGWorld, k32ARGBPixelFormat, &scaleRect, NULL, NULL, kNativeEndianPixMap); // set its graphics world if (noErr != (err = SGSetGWorld(itsSeqGrab.it, itsGWorld, NULL))) LFATAL("SGSetGWorld() failed (err=%ld)", (long) err); // specify the destination data reference for a record operation // tell it we're not making a movie if the flag seqGrabDontMakeMovie // is used, the sequence grabber still calls your data function, but // does not write any data to the movie file writeType will always // be set to seqGrabWriteAppend if (noErr != (err = SGSetDataRef(itsSeqGrab.it, 0, 0, seqGrabDontMakeMovie | seqGrabDataProcIsInterruptSafe))) LFATAL("SGSetDataRef() failed (err=%ld)", (long) err); Impl::SGChannelHolder sgchanSound(&itsSeqGrab.it); if (noErr != (err = SGNewChannel(itsSeqGrab.it, VideoMediaType, &itsSGChanVideo.it))) LFATAL("SGNewChannel(video) failed (err=%ld)", (long) err); if (noErr != (err = SGNewChannel(itsSeqGrab.it, SoundMediaType, &sgchanSound.it))) { // don't care if we couldn't get a sound channel sgchanSound.it = NULL; LERROR("SGNewChannel(audio) failed (err=%ld)", (long) err); } // get the active rectangle Rect srcBounds; if (noErr != (err = SGGetSrcVideoBounds(itsSGChanVideo.it, &srcBounds))) LFATAL("SGGetSrcVideoBounds() failed (err=%ld)", (long) err); // we always want all the source setVideoChannelBounds(itsSGChanVideo.it, &srcBounds, &srcBounds); // set usage for new video channel to avoid playthrough // note we don't set seqGrabPlayDuringRecord if (noErr != (err = SGSetChannelUsage(itsSGChanVideo.it, seqGrabRecord | seqGrabLowLatencyCapture | seqGrabAlwaysUseTimeBase))) LFATAL("SGSetChannelUsage(video) failed (err=%ld)", (long) err); if (noErr != (err = SGSetChannelUsage(sgchanSound.it, seqGrabRecord | //seqGrabPlayDuringRecord | seqGrabLowLatencyCapture | seqGrabAlwaysUseTimeBase))) LERROR("SGSetChannelUsage(audio) failed (err=%ld)", (long) err); // specify a sequence grabber data function if (noErr != (err = SGSetDataProc(itsSeqGrab.it, NewSGDataUPP(Impl::grabDataProc), (long)(this)))) LFATAL("SGSetDataProc() failed (err=%ld)", (long) err); SGSetChannelRefCon(itsSGChanVideo.it, (long)(this)); // set up the video bottlenecks so we can get our queued frame count VideoBottles vb = { 0 }; if (noErr != (err = SGGetVideoBottlenecks(itsSGChanVideo.it, &vb))) LFATAL("SGGetVideoBottlenecks() failed (err=%ld)", (long) err); vb.procCount = 9; // there are 9 bottleneck procs; this must be filled in vb.grabCompressCompleteProc = NewSGGrabCompressCompleteBottleUPP (Impl::grabCompressCompleteBottle); if (noErr != (err = SGSetVideoBottlenecks(itsSGChanVideo.it, &vb))) LFATAL("SGSetVideoBottlenecks() failed (err=%ld)", (long) err); SGSetFrameRate(itsSGChanVideo.it, FixRatio(30, 1)); }