Ejemplo n.º 1
0
void pix_videoDarwin :: InitSeqGrabber()
{
    OSErr anErr;
    Rect m_srcRect = {0,0, m_vidYSize, m_vidXSize};

    SGDeviceList    devices;
    short            deviceIndex,inputIndex;
    short            deviceCount = 0;
    SGDeviceInputList theSGInputList = NULL;
    bool showInputsAsDevices;
//    UserData     *uD;


    /*
    int num_components = 0;
    Component c = 0;
    ComponentDescription cd;

     cd.componentType = SeqGrabComponentType;
     cd.componentSubType = 0;
     cd.componentManufacturer = 0;
     cd.componentFlags = 0;
     cd.componentFlagsMask = 0;

     while((c = FindNextComponent(c, &cd)) != 0) {
       num_components++;  }                 // add component c to the list.
  //   post("number of SGcomponents: %d",num_components);
  */
    m_sg = OpenDefaultComponent(SeqGrabComponentType, 0);
    if(m_sg==NULL){
        error("could not open default component");
        return;
    }
    anErr = SGInitialize(m_sg);
    if(anErr!=noErr){
        error("could not initialize SG error %d",anErr);
        return;
    }

    anErr = SGSetDataRef(m_sg, 0, 0, seqGrabDontMakeMovie);
        if (anErr != noErr){
            error("dataref failed with error %d",anErr);
        }

    anErr = SGNewChannel(m_sg, VideoMediaType, &m_vc);
    if(anErr!=noErr){
        error("could not make new SG channnel error %d",anErr);
        return;
    }

     anErr = SGGetChannelDeviceList(m_vc, sgDeviceListIncludeInputs, &devices);
    if(anErr!=noErr){
        error("could not get SG channnel Device List");
    }else{
        deviceCount = (*devices)->count;
        deviceIndex = (*devices)->selectedIndex;
        logpost(NULL, 3, "SG channnel Device List count %d index %d",deviceCount,deviceIndex);
        int i;
        for (i = 0; i < deviceCount; i++){
	  logpost(NULL, 3, "SG channnel Device List  %.*s",
	       (*devices)->entry[i].name[0],
	       (*devices)->entry[i].name+1);
            }
        SGGetChannelDeviceAndInputNames(m_vc, NULL, NULL, &inputIndex);

        showInputsAsDevices = ((*devices)->entry[deviceIndex].flags) & sgDeviceNameFlagShowInputsAsDevices;

        theSGInputList = ((SGDeviceName *)(&((*devices)->entry[deviceIndex])))->inputs; //fugly

        //we should have device names in big ass undocumented structs

        //walk through the list
        //for (i = 0; i < deviceCount; i++){
        for (i = 0; i < inputIndex; i++){
            logpost(NULL, 3, "SG channnel Input Device List %d %.*s",
		 i,
		 (*theSGInputList)->entry[i].name[0],
		 (*theSGInputList)->entry[i].name+1);
        }


    }

    //this call sets the input device
    if (m_inputDevice > 0 && m_inputDevice < deviceCount) //check that the device is not out of bounds
        //anErr = SGSetChannelDeviceInput(m_vc,m_inputDevice);
        logpost(NULL, 3, "SGSetChannelDevice trying %s", 
	     (*devices)->entry[m_inputDevice].name[0],
	     (*devices)->entry[m_inputDevice].name+1);
        anErr = SGSetChannelDevice(m_vc, (*devices)->entry[m_inputDevice].name);

        if(anErr!=noErr) error("SGSetChannelDevice returned error %d",anErr);

        anErr = SGSetChannelDeviceInput(m_vc,m_inputDeviceChannel);

        if(anErr!=noErr) error("SGSetChannelDeviceInput returned error %d",anErr);

    /*  //attempt to save SG settings to disk
    NewUserData(uD);
    SGGetSettings(m_sg,uD,0);
    short uDCount;
    uDCount = CountUserDataType(*uD,sgClipType);
    post("UserDataType count %d",uDCount);

    Handle myHandle;

    PutUserDataIntoHandle(*uD,myHandle);

    int myFile;
    myFile = open("/Users/lincoln/Documents/temp",O_CREAT | O_RDWR, 0600);
    write(myFile,myHandle,4096);
    close(myFile);
    */

    //grab the VDIG info from the SGChannel
    m_vdig = SGGetVideoDigitizerComponent(m_vc);
    vdigErr = VDGetDigitizerInfo(m_vdig,&m_vdigInfo); //not sure if this is useful

    Str255    vdigName;
    memset(vdigName,0,255);
    vdigErr = VDGetInputName(m_vdig,m_inputDevice,vdigName);
    logpost(NULL, 3, "vdigName is %s",vdigName); // pascal string?

    Rect vdRect;
    vdigErr = VDGetDigitizerRect(m_vdig,&vdRect);
    logpost(NULL, 3, "digitizer rect is top %d bottom %d left %d right %d",vdRect.top,vdRect.bottom,vdRect.left,vdRect.right);

    vdigErr = VDGetActiveSrcRect(m_vdig,0,&vdRect);
    logpost(NULL, 3, "active src rect is top %d bottom %d left %d right %d",vdRect.top,vdRect.bottom,vdRect.left,vdRect.right);

    anErr = SGSetChannelBounds(m_vc, &m_srcRect);
    if(anErr!=noErr){
        error("could not set SG ChannelBounds ");
    }

    anErr = SGSetVideoRect(m_vc, &m_srcRect);
    if(anErr!=noErr){
        error("could not set SG Rect ");
    }

    anErr = SGSetChannelUsage(m_vc, seqGrabPreview);
    if(anErr!=noErr){
        error("could not set SG ChannelUsage ");
    }

    switch (m_quality){
    case 0:
        anErr = SGSetChannelPlayFlags(m_vc, channelPlayNormal);
        post("set SG NormalQuality");
        break;
    case 1:
        anErr = SGSetChannelPlayFlags(m_vc, channelPlayHighQuality);
        post("set SG HighQuality");
        break;
    case 2:
        anErr = SGSetChannelPlayFlags(m_vc, channelPlayFast);
        post("set SG FastQuality");
        break;
    case 3:
        anErr = SGSetChannelPlayFlags(m_vc, channelPlayAllData);
        post("set SG PlayAlldata");
        break;
    }
    if (m_colorspace==GL_BGRA_EXT){
      m_pixBlock.image.xsize = m_vidXSize;
      m_pixBlock.image.ysize = m_vidYSize;
      m_pixBlock.image.setCsizeByFormat(GL_RGBA_GEM);
      m_pixBlock.image.reallocate();
      m_rowBytes = m_vidXSize*4;
      anErr = QTNewGWorldFromPtr (&m_srcGWorld,
                                  k32ARGBPixelFormat,
                                  &m_srcRect,
                                  NULL,
                                  NULL,
                                  0,
                                  m_pixBlock.image.data,
                                  m_rowBytes);

      post ("using RGB");
    }else{
      m_pixBlock.image.xsize = m_vidXSize;
      m_pixBlock.image.ysize = m_vidYSize;
      m_pixBlock.image.csize = 2;
      m_pixBlock.image.format = GL_YCBCR_422_APPLE;
#ifdef __VEC__
      m_pixBlock.image.type = GL_UNSIGNED_SHORT_8_8_REV_APPLE;
#else
      m_pixBlock.image.type = GL_UNSIGNED_SHORT_8_8_APPLE;
#endif

      m_pixBlock.image.reallocate();

      m_rowBytes = m_vidXSize*2;
      anErr = QTNewGWorldFromPtr (&m_srcGWorld,
                                  //  k422YpCbCr8CodecType,

                                  k422YpCbCr8PixelFormat,
                                  // '2vuy',
                                  // kComponentVideoUnsigned,
                                  &m_srcRect,
                                  NULL,
                                  NULL,
                                  0,
                                  m_pixBlock.image.data,
                                  m_rowBytes);
      post ("using YUV");
    }

    if (anErr!= noErr)
      {
      error("%d error at QTNewGWorldFromPtr", anErr);
      return;
    }
    if (NULL == m_srcGWorld)
      {
        error("could not allocate off screen");
        return;
      }
    SGSetGWorld(m_sg,(CGrafPtr)m_srcGWorld, NULL);
    SGStartPreview(m_sg); //moved to starttransfer?
    m_haveVideo = 1;
}
Ejemplo n.º 2
0
// 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);
}
Ejemplo n.º 3
0
// ######################################################################
OSErr QuickTimeGrabber::Impl::grabData(SGChannel c, Ptr p,
                                       long len, TimeValue time)
{
  if (itsGotFrame)
    {
      LDEBUG("already got a frame on this iteration");
      return noErr;
    }

  // we only care about the video
  if (c != itsSGChanVideo.it)
    {
      return noErr;
    }

  // reset frame and time counters after a stop/start
  if (time < itsPrevTime)
    {
      LDEBUG("resetting frame/time counters (current=%ld, last=%ld)",
             (long) time, (long) itsPrevTime);
      itsPrevTime = 0;
      itsFrameCount = 0;
    }

  if (itsTimeScale == 0)
    {
      LDEBUG("setting up time scale & timebase");

      Fixed framesPerSecond;
      long  milliSecPerFrameIgnore, bytesPerSecondIgnore;

      // first time here so get the time scale & timebase
      if (noErr != SGGetChannelTimeScale(c, &itsTimeScale))
        {
          itsErrorMsg = "SGGetChannelTimeScale() failed";
          return OSErr(-1);
        }

      if (noErr != SGGetTimeBase(itsSeqGrab.it, &itsTimeBase))
        {
          itsErrorMsg = "SGGetTimeBase() failed";
          return OSErr(-1);
        }

      if (noErr != VDGetDataRate(SGGetVideoDigitizerComponent(c),
                                 &milliSecPerFrameIgnore,
                                 &framesPerSecond,
                                 &bytesPerSecondIgnore))
        {
          itsErrorMsg = "VDGetDataRate() failed";
          return OSErr(-1);
        }
    }

  if (itsDrawSeq == 0)
    {
      LDEBUG("setting up decompression sequence");

      // set up decompression sequence
      ImageDescriptionHandle imageDesc =
        (ImageDescriptionHandle)NewHandle(0);

      // retrieve a channel's current sample description, the channel
      // returns a sample description that is appropriate to the type
      // of data being captured
      if (noErr != SGGetChannelSampleDescription(c, (Handle)imageDesc))
        {
          itsErrorMsg = "SGGetChannelSampleDescription() failed";
          return OSErr(-1);
        }

      // make a scaling matrix for the sequence
      Rect sourceRect = { 0, 0 };
      sourceRect.right = (**imageDesc).width;
      sourceRect.bottom = (**imageDesc).height;

      Rect scaleRect;
      GetPixBounds(GetGWorldPixMap(itsGWorld), &scaleRect);

      // if DV do high quality 720x480 both fields
      CodecFlags cFlags =
        (kDVCNTSCCodecType == (**imageDesc).cType)
        ? codecHighQuality
        : codecNormalQuality;

      MatrixRecord scaleMatrix;
      RectMatrix(&scaleMatrix, &sourceRect, &scaleRect);

      LINFO("sourceRect = %dx%d, scaleRect = %dx%d",
            sourceRect.right - sourceRect.left,
            sourceRect.bottom - sourceRect.top,
            scaleRect.right - scaleRect.left,
            scaleRect.bottom - scaleRect.top);

      // begin the process of decompressing a sequence of frames this
      // is a set-up call and is only called once for the sequence -
      // the ICM will interrogate different codecs and construct a
      // suitable decompression chain, as this is a time consuming
      // process we don't want to do this once per frame (eg. by using
      // DecompressImage) for more information see Ice Floe #8
      // http://developer.apple.com/quicktime/icefloe/dispatch008.html
      // the destination is specified as the GWorld
      CGrafPtr dest = itsGWorld;
      if (noErr != DecompressSequenceBeginS
          (&itsDrawSeq,     // pointer to field to receive unique ID for sequence
           imageDesc,       // handle to image description structure
           p,               // points to the compressed image data
           len,             // size of the data buffer
           dest,            // port for the DESTINATION image
           NULL,            // graphics device handle, if port is set, set to NULL
           NULL,            // decompress the entire source image - no source extraction
           &scaleMatrix,    // transformation matrix
           srcCopy,         // transfer mode specifier
           (RgnHandle)NULL, // clipping region in dest. coordinate system to use as a mask
           0,               // flags
           cFlags,          // accuracy in decompression
           bestSpeedCodec)) // compressor identifier or special identifiers ie. bestSpeedCodec
        {
          itsErrorMsg = "DSeqBegin failed";
          return OSErr(-1);
        }

      DisposeHandle((Handle)imageDesc);

    } // itsDrawSeq == 0

  // get the TimeBase time and figure out the delta between that time
  // and this frame time
  const TimeValue timeBaseTime = GetTimeBaseTime(itsTimeBase,
                                                 itsTimeScale, NULL);
  const TimeValue timeBaseDelta = timeBaseTime - time;
  const TimeValue frameTimeDelta = time - itsPrevTime;

  if (timeBaseDelta < 0)
    {
      itsErrorMsg = "bogus timeBaseDelta";
      return OSErr(-1);
    }

  // if we have more than one queued frame and our capture rate drops
  // below 10 frames, skip the frame to try and catch up
  if ((itsQueuedFrameCount > 1)
      &&  ((itsTimeScale / frameTimeDelta) < 10)
      && (itsSkipFrameCount < 15))
    {
      LDEBUG("dropping frame");
      ++itsSkipFrameCount;
      ++itsSkipFrameCountTotal;
    }
  else
    {
      itsFrameCount++;

      CodecFlags ignore;

      // decompress a frame into the window - can queue a frame for async decompression when passed in a completion proc
      if (noErr != DecompressSequenceFrameS
          (itsDrawSeq, // sequence ID returned by DecompressSequenceBegin
           p,          // pointer to compressed image data
           len,        // size of the buffer
           0,          // in flags
           &ignore,    // out flags
           NULL))      // async completion proc
        {
          itsErrorMsg =  "DSeqFrameS failed";
          return OSErr(-1);
        }

      // get the information we need from the GWorld
      Rect pbound;
      GetPixBounds(GetGWorldPixMap(itsGWorld), &pbound);

      char* const baseAddr =
        GetPixBaseAddr(GetGWorldPixMap(itsGWorld));

      const long rowBytes =
        QTGetPixMapHandleRowBytes(GetGWorldPixMap(itsGWorld));

      itsCurrentImage.resize(Dims(pbound.right - pbound.left,
                                     pbound.bottom - pbound.top));

      Image<PixRGB<byte> >::iterator itr = itsCurrentImage.beginw();

      for (int y = pbound.top; y < pbound.bottom; ++y)
        {
          char* p = baseAddr + rowBytes * (y-pbound.top);

          for (int x = pbound.left; x < pbound.right; ++x)
            {
              const UInt32 color = *((UInt32*)(p) + x - pbound.left);
              const UInt32 R = (color & 0x00FF0000) >> 16;
              const UInt32 G = (color & 0x0000FF00) >> 8;
              const UInt32 B = (color & 0x000000FF) >> 0;

              *itr++ = PixRGB<byte>(R,G,B);
            }
        }

      itsSkipFrameCount = 0;
      itsPrevTime = time;
      itsGotFrame = true;
    }

  // status information
  const float fps = (float)itsTimeScale / (float)frameTimeDelta;
  const float averagefps = ((float)itsFrameCount * (float)itsTimeScale) / (float)time;
  const UInt8 minutes = (time / itsTimeScale) / 60;
  const UInt8 seconds = (time / itsTimeScale) % 60;
  const UInt8 frames = (time % itsTimeScale) / frameTimeDelta;
  LDEBUG("#%06ld t:%ld nq:%u, %02d:%02d.%02d, fps:%5.1f av:%5.1f",
         itsFrameCount, time, itsQueuedFrameCount,
         minutes, seconds, frames, fps, averagefps);

  return noErr;
}