// Thread run method void QuicktimeLiveImageStream::run() { ComponentResult result = noErr; bool done = false; //memset( data(), 255, 720*250*4); while (!done) { // Do some funky rotational memset // void * memset ( void * ptr, int value, size_t num ); //memset // dirty(); if (g_s_use_sg) { result = SGIdle(m_gSeqGrabber); if (result != noErr) { OSG_FATAL << "SGIdle : error" << std::endl; } } //OpenThreads::Thread::microSleep(250000); // 25fps (1,000,000 = 1 fps) //OpenThreads::Thread::microSleep(50000); // 200fps (1,000,000 = 1 fps) //OpenThreads::Thread::microSleep(25000); // 400fps (1,000,000 = 1 fps) // Ridiculous OpenThreads::Thread::microSleep(10000); // 1000fps (1,000,000 = 1 fps) } }
//-------------------------------------------------------------------- void ofQuickTimeGrabber::update(){ //--------------------------------- #ifdef OF_VIDEO_CAPTURE_QUICKTIME //--------------------------------- if (bGrabberInited == true){ SGIdle(gSeqGrabber); // set the top pixel alpha = 0, so we can know if it // was a new frame or not.. // or else we will process way more than necessary // (ie opengl is running at 60fps +, capture at 30fps) if (bHavePixelsChanged){ #if defined(TARGET_OSX) && defined(__BIG_ENDIAN__) convertPixels(offscreenGWorldPixels, pixels.getPixels(), width, height); #endif } } // newness test for quicktime: if (bGrabberInited == true){ bIsFrameNew = false; if (bHavePixelsChanged == true){ bIsFrameNew = true; bHavePixelsChanged = false; } } //--------------------------------- #endif //--------------------------------- }
static GstFlowReturn gst_osx_video_src_create (GstPushSrc * src, GstBuffer ** buf) { GstOSXVideoSrc *self = GST_OSX_VIDEO_SRC (src); ComponentResult err; GstCaps *caps; //GstClock * clock; // ###: we need to sleep between calls to SGIdle. originally, the sleeping // was done using gst_clock_id_wait(), but it turns out that approach // doesn't work well. it has two issues: // 1) every so often, gst_clock_id_wait() will block for a much longer // period of time than requested (upwards of a minute) causing video // to freeze until it finally returns. this seems to happen once // every few minutes, which probably means something like 1 in every // several hundred calls gst_clock_id_wait() does the wrong thing. // 2) even when the gst_clock approach is working properly, it uses // quite a bit of cpu in comparison to a simple usleep(). on one // test machine, using gst_clock_id_wait() caused osxvideosrc to use // nearly 100% cpu, while using usleep() brough the usage to less // than 10%. // // so, for now, we comment out the gst_clock stuff and use usleep. //clock = gst_system_clock_obtain (); do { err = SGIdle (self->seq_grab); if (err != noErr) { GST_ERROR_OBJECT (self, "SGIdle returned %d", (int) err); gst_object_unref (clock); return GST_FLOW_UNEXPECTED; } if (self->buffer == NULL) { /*GstClockID clock_id; clock_id = gst_clock_new_single_shot_id (clock, (GstClockTime) (gst_clock_get_time(clock) + (GST_SECOND / ((float)FRAMERATE * 2)))); gst_clock_id_wait (clock_id, NULL); gst_clock_id_unref (clock_id); */ usleep (1000000 / (FRAMERATE * 2)); } } while (self->buffer == NULL); //gst_object_unref (clock); *buf = self->buffer; self->buffer = NULL; caps = gst_pad_get_caps (GST_BASE_SRC_PAD (src)); gst_buffer_set_caps (*buf, caps); gst_caps_unref (caps); return GST_FLOW_OK; }
Boolean QTApp_HandleEvent (EventRecord *theEvent) { Boolean myEventHandled = false; // grant the sequence grabber some processor time if (gSeqGrabber != NULL) SGIdle(gSeqGrabber); return(myEventHandled); }
void QTApp_Idle (WindowReference theWindow) { WindowObject myWindowObject = NULL; GrafPtr mySavedPort; GetPort(&mySavedPort); MacSetPort(QTFrame_GetPortFromWindowReference(theWindow)); myWindowObject = QTFrame_GetWindowObjectFromWindow(theWindow); if (myWindowObject != NULL) { MovieController myMC = NULL; myMC = (**myWindowObject).fController; if (myMC != NULL) { // run any idle-time tasks for the movie #if TARGET_OS_MAC // restore the cursor to the arrow // if it's outside the front movie window or outside the window's visible region if (theWindow == QTFrame_GetFrontMovieWindow()) { Rect myRect; Point myPoint; RgnHandle myVisRegion; Cursor myArrow; GetMouse(&myPoint); myVisRegion = NewRgn(); GetPortVisibleRegion(QTFrame_GetPortFromWindowReference(theWindow), myVisRegion); GetWindowPortBounds(theWindow, &myRect); if (!MacPtInRect(myPoint, &myRect) || !PtInRgn(myPoint, myVisRegion)) MacSetCursor(GetQDGlobalsArrow(&myArrow)); DisposeRgn(myVisRegion); } #endif // TARGET_OS_MAC } } // grant the sequence grabber some processor time if (gSeqGrabber != NULL) SGIdle(gSeqGrabber); MacSetPort(mySavedPort); }
///////////////////////////////////////////////////////// // render // ///////////////////////////////////////////////////////// void pix_videoDarwin :: render(GemState *state) { OSErr err; // short frameCount = 0; // Boolean *done; if (m_auto || m_banged) { err = SGIdle(m_sg); if (err != noErr){ error("SGIdle failed with error %d",err); m_haveVideo = 0; } else { //this doesn't do anything so far //VDCompressDone(m_vdig,frameCount,data,size,similar,time); //err = SGGrabFrameComplete(m_vc,frameCount,done); //if (err != noErr) error("SGGrabCompressComplete failed with error %d",err); //post("SGGrabFramecomplete done %d framecount = %d",done[0],frameCount); m_haveVideo = 1; m_newFrame = 1; } if (!m_haveVideo) { post("no video yet"); return; } // derSwizzler(m_pixBlock.image); m_pixBlock.newimage = m_newFrame; state->image = &m_pixBlock; m_newFrame = 0; }else { m_newFrame = 0; m_pixBlock.newimage = m_newFrame; state->image = &m_pixBlock; } m_banged = false; }
// ###################################################################### GenericFrame QuickTimeGrabber::Impl::readFrame() { if (!itsStreamStarted) this->startStream(); while (1) { itsGotFrame = false; itsErrorMsg = ""; if (noErr != SGIdle(itsSeqGrab.it)) LFATAL("SGIdle() failed"); if (itsErrorMsg.length() > 0) { // some error specific to SGIdle occurred - any errors // returned from the data proc will also show up here and we // don't want to write over them // in QT 4 you would always encounter a cDepthErr error // after a user drags the window, this failure condition has // been greatly relaxed in QT 5 it may still occur but // should only apply to vDigs that really control the screen // you don't always know where these errors originate from, // some may come from the VDig... LFATAL("QuickTimeGrabber error during SGIdle (%s)", itsErrorMsg.c_str()); // ...to fix this we simply call SGStop and SGStartRecord // again calling stop allows the SG to release and // re-prepare for grabbing hopefully fixing any problems, // this is obviously a very relaxed approach SGStop(itsSeqGrab.it); SGStartRecord(itsSeqGrab.it); } if (itsGotFrame) return GenericFrame(itsCurrentImage); usleep(20000); } }
static void v4m_process(MSFilter * obj){ V4lState *s=(V4lState*)obj->data; uint32_t timestamp; int cur_frame; if (s->frame_count==-1){ s->start_time=obj->ticker->time; s->frame_count=0; } if (s->seqgrab!=NULL) { SGIdle(s->seqgrab); } cur_frame=((obj->ticker->time-s->start_time)*s->fps/1000.0); if (cur_frame>=s->frame_count){ mblk_t *om=NULL; ms_mutex_lock(&s->mutex); /*keep the most recent frame if several frames have been captured */ if (s->seqgrab!=NULL){ om=getq(&s->rq); }else{ if (s->usemire){ om=dupmsg(v4m_make_mire(s)); }else { mblk_t *tmpm=v4m_make_nowebcam(s); if (tmpm) om=dupmsg(tmpm); } } ms_mutex_unlock(&s->mutex); if (om!=NULL){ timestamp=obj->ticker->time*90;/* rtp uses a 90000 Hz clockrate for video*/ mblk_set_timestamp_info(om,timestamp); mblk_set_marker_info(om,TRUE); ms_queue_put(obj->outputs[0],om); /*ms_message("picture sent");*/ s->frame_count++; } }else flushq(&s->rq,0); }
unsigned char* macsgCamera::getFrame() { OSErr result = SGIdle(sg); if (result != noErr) { fprintf(stderr, "SGIdle failed\n"); return NULL; } switch (colour) { case false: { for(int i=0;i<width*height;i++) { pbuffer[i]=256-buffer[i]; } break; } case true: { memcpy(pbuffer,buffer,width*height*bytes); break; } } return pbuffer; }
//-------------------------------------------------------------------- void ofVideoGrabber::grabFrame(){ //--------------------------------- #ifdef OF_VIDEO_CAPTURE_QUICKTIME //--------------------------------- if (bGrabberInited == true){ SGIdle(gSeqGrabber); // set the top pixel alpha = 0, so we can know if it // was a new frame or not.. // or else we will process way more than necessary // (ie opengl is running at 60fps +, capture at 30fps) if (offscreenGWorldPixels[0] != 0x00){ offscreenGWorldPixels[0] = 0x00; bHavePixelsChanged = true; convertPixels(offscreenGWorldPixels, pixels, width, height); if (bUseTexture){ tex.loadData(pixels, width, height, GL_RGB); } } } // newness test for quicktime: if (bGrabberInited == true){ bIsFrameNew = false; if (bHavePixelsChanged == true){ bIsFrameNew = true; bHavePixelsChanged = false; } } //--------------------------------- #endif //--------------------------------- //--------------------------------- #ifdef OF_VIDEO_CAPTURE_DIRECTSHOW //--------------------------------- if (bGrabberInited == true){ bIsFrameNew = false; if (VI.isFrameNew(device)){ bIsFrameNew = true; /* rescale -- currently this is nearest neighbor scaling not the greatest, but fast this can be optimized too with pointers, etc better -- make sure that you ask for a "good" size.... */ unsigned char * viPixels = VI.getPixels(device, true, true); if (bDoWeNeedToResize == true){ int inputW = VI.getWidth(device); int inputH = VI.getHeight(device); float scaleW = (float)inputW / (float)width; float scaleH = (float)inputH / (float)height; for(int i=0;i<width;i++){ for(int j=0;j<height;j++){ float posx = i * scaleW; float posy = j * scaleH; /* // start of calculating // for linear interpolation int xbase = (int)floor(posx); int xhigh = (int)ceil(posx); float pctx = (posx - xbase); int ybase = (int)floor(posy); int yhigh = (int)ceil(posy); float pcty = (posy - ybase); */ int posPix = (((int)posy * inputW * 3) + ((int)posx * 3)); pixels[(j*width*3) + i*3 ] = viPixels[posPix ]; pixels[(j*width*3) + i*3 + 1] = viPixels[posPix+1]; pixels[(j*width*3) + i*3 + 2] = viPixels[posPix+2]; } } } else { memcpy(pixels, viPixels, width*height*3); } if (bUseTexture){ tex.loadData(pixels, width, height, GL_RGB); } } } //--------------------------------- #endif //--------------------------------- //--------------------------------- #ifdef OF_VIDEO_CAPTURE_UNICAP //-------------------------------- if (bGrabberInited){ bIsFrameNew = ucGrabber.getFrameUC(&pixels); if(bIsFrameNew) { if (bUseTexture){ tex.loadData(pixels, width, height, GL_RGB); } } } //--------------------------------- #endif //--------------------------------- //--------------------------------- #ifdef OF_VIDEO_CAPTURE_GSTREAMER //-------------------------------- if (bGrabberInited){ gstUtils.update(); bIsFrameNew = gstUtils.isFrameNew(); if(bIsFrameNew) { if (bUseTexture){ tex.loadData(gstUtils.getPixels(), width, height, GL_RGB); } } } //--------------------------------- #endif //--------------------------------- //--------------------------------- #ifdef OF_VIDEO_CAPTURE_V4L //-------------------------------- if (bV4LGrabberInited == true){ bIsFrameNew = getFrameV4L(pixels); if(bIsFrameNew) { if (bUseTexture){ tex.loadData(pixels, width, height, GL_RGB); } } } //--------------------------------- #endif //--------------------------------- }