//////////////////////////////////////////////////////// // // GEM - Graphics Environment for Multimedia // // zmoelnig@iem.kug.ac.at // // Implementation file // // Copyright (c) 2010-2011 IOhannes m zmölnig. forum::für::umläute. IEM. zmoelnig@iem.at // For information on usage and redistribution, and for a DISCLAIMER OF ALL // WARRANTIES, see the file, "LICENSE.txt" // ///////////////////////////////////////////////////////// #ifdef HAVE_CONFIG_H # include "config.h" #endif #if defined HAVE_LIBPYLON # define HAVE_PYLON #endif #ifdef HAVE_PYLON #include "videoPYLON.h" #include "plugins/PluginFactory.h" #include using namespace gem::plugins; #define NUM_BUFFERS 8 #include "Gem/RTE.h" #include "Gem/Exception.h" #if 0 # define debug ::post #else # define debug #endif using namespace Basler_GigECameraParams; using namespace Basler_GigEStreamParams; #include "CameraProperties.h" #include "StreamGrabberProperties.h" // Constructor allocates the image buffer class videoPYLON::CGrabBuffer { static int buffercount; public: CGrabBuffer(const size_t ImageSize) : m_pBuffer(NULL) { buffercount++; m_pBuffer = new uint8_t[ ImageSize ]; if (NULL == m_pBuffer) { GenICam::GenericException e("Not enough memory to allocate image buffer", __FILE__, __LINE__); throw e; } } // Freeing the memory ~CGrabBuffer() { if (NULL != m_pBuffer) delete[] m_pBuffer; buffercount--; } uint8_t* GetBufferPointer(void) { return m_pBuffer; } Pylon::StreamBufferHandle GetBufferHandle(void) { return m_hBuffer; } void SetBufferHandle(Pylon::StreamBufferHandle hBuffer) { m_hBuffer = hBuffer; }; protected: uint8_t *m_pBuffer; Pylon::StreamBufferHandle m_hBuffer; }; int videoPYLON::CGrabBuffer::buffercount=0; struct videoPYLON::Converter { #ifdef HAVE_LIBPYLONUTILITY Pylon::CPixelFormatConverter*converter; #endif imageStruct image; struct Pylon::SImageFormat inFormat; struct Pylon::SOutputImageFormat outFormat; Converter(void) #ifdef HAVE_LIBPYLONUTILITY : converter(NULL) #endif { } ~Converter(void) { destroyConverter(); } void destroyConverter(void) { #ifdef HAVE_LIBPYLONUTILITY if(converter) { delete converter; converter=NULL; } #endif } void makeConverter(const struct Pylon::SImageFormat&format) { destroyConverter(); using namespace Pylon; bool rgba_out=false; bool need_converter=true; #ifdef HAVE_LIBPYLONUTILITY switch(format.PixelFormat) { case PixelType_Mono8: case PixelType_Mono8signed: /* no converter needed */ need_converter=false; rgba_out=false; break; case PixelType_RGBA8packed: /* no converter needed */ need_converter=false; rgba_out=true; break; case PixelType_Mono10: case PixelType_Mono12: case PixelType_Mono16: converter= new Pylon::CPixelFormatConverterGamma (); // converter= new Pylon::CPixelFormatConverterTruncate (); rgba_out=false; break; case PixelType_Mono10packed: case PixelType_Mono12packed: converter= new Pylon::CPixelFormatConverterGammaPacked (); // converter= new Pylon::CPixelFormatConverterTruncatePacked (); rgba_out=false; break; case PixelType_BayerGR8: case PixelType_BayerRG8: case PixelType_BayerGB8: case PixelType_BayerBG8: case PixelType_BayerGR10: case PixelType_BayerRG10: case PixelType_BayerGB10: case PixelType_BayerBG10: case PixelType_BayerGR12: case PixelType_BayerRG12: case PixelType_BayerGB12: case PixelType_BayerBG12: case PixelType_BayerGB12Packed: case PixelType_BayerGR12Packed: case PixelType_BayerRG12Packed: case PixelType_BayerBG12Packed: case PixelType_BayerGR16: case PixelType_BayerRG16: case PixelType_BayerGB16: case PixelType_BayerBG16: converter= new Pylon::CPixelFormatConverterBayer (); rgba_out=true; break; case PixelType_RGB8planar: case PixelType_RGB10planar: case PixelType_RGB12planar: case PixelType_RGB16planar: case PixelType_RGB8packed: case PixelType_BGR8packed: case PixelType_BGRA8packed: case PixelType_RGB10packed: case PixelType_BGR10packed: case PixelType_RGB12packed: case PixelType_BGR12packed: case PixelType_BGR10V1packed: case PixelType_BGR10V2packed: converter= new Pylon::CPixelFormatConverterRGB (); rgba_out=true; break; case PixelType_YUV422_YUYV_Packed: converter= new Pylon::CPixelFormatConverterYUV422YUYV(); rgba_out=true; break; case PixelType_YUV422packed: converter= new Pylon::CPixelFormatConverterYUV422(); rgba_out=true; break; case PixelType_YUV411packed: case PixelType_YUV444packed: case PixelType_RGB12V1packed: // ? break; } if(NULL==converter && need_converter) { error("PYLON: could not find a converter for given colorspace"); } if(converter) converter->Init(format); #endif if(rgba_out) { image.setCsizeByFormat(GL_RGBA); } else { image.setCsizeByFormat(GL_LUMINANCE); } } static struct Pylon::SImageFormat getInFormat(const Pylon::GrabResult&Result) { using namespace Pylon; struct SImageFormat imageFormat; const enum PixelType pixelType=Result.GetPixelType(); imageFormat.Width =Result.GetSizeX(); imageFormat.Height=Result.GetSizeY(); imageFormat.PixelFormat=pixelType; imageFormat.LinePitch=IsPacked(pixelType)? 0: (7+Result.GetSizeX()*BitPerPixel(pixelType)) >>3; return imageFormat; } static struct Pylon::SOutputImageFormat getOutFormat(const imageStruct&img) { using namespace Pylon; struct SOutputImageFormat imageFormat; switch(img.format) { case GL_RGBA: imageFormat.LinePitch=img.xsize*img.csize; imageFormat.PixelFormat=Pylon::PixelType_RGBA8packed; break; case GL_LUMINANCE: default: imageFormat.LinePitch=img.xsize*img.csize; imageFormat.PixelFormat=Pylon::PixelType_Mono8; break; } return imageFormat; } bool convertFrom(Pylon::GrabResult Result) { const struct Pylon::SImageFormat format=getInFormat(Result); bool init=false; #ifdef HAVE_LIBPYLONUTILITY if(!converter)init=true; if(converter && !converter->IsInitialized())init=true; #endif if(format!=inFormat)init=true; if(init) { makeConverter(format); inFormat=format; } image.xsize=inFormat.Width; image.ysize=inFormat.Height; image.reallocate(); if(0) {; #ifdef HAVE_LIBPYLONUTILITY } else if(converter) { const struct Pylon::SOutputImageFormat oformat=getOutFormat(image); converter->Convert(image.data, image.xsize*image.ysize*image.csize, Result.Buffer(), Result.GetPayloadSize(), format, oformat); #endif } else { if(image.format==GL_RGBA) image.fromRGBA(reinterpret_cast(Result.Buffer())); else image.fromGray(reinterpret_cast(Result.Buffer())); } return true; } bool convertTo(imageStruct&img) { img.convertFrom(&image); } }; ///////////////////////////////////////////////////////// // // videoPYLON // ///////////////////////////////////////////////////////// // Constructor // ///////////////////////////////////////////////////////// REGISTER_VIDEOFACTORY("pylon", videoPYLON); videoPYLON :: videoPYLON() : videoBase("pylon") , m_factory(NULL) , m_camera(NULL) , m_grabber(NULL) , m_converter(new Converter()) , m_numBuffers(NUM_BUFFERS) { m_width=0; m_height=0; try { m_factory = &Pylon::CTlFactory::GetInstance(); Pylon::TlInfoList_t tli; int count= m_factory->EnumerateTls (tli); int i=0; for(i=0; iGetWaitObject().Wait(3000)) { Pylon::GrabResult Result; m_grabber->RetrieveResult(Result); switch(Result.Status()) { case Pylon::Grabbed: { m_converter->convertFrom(Result); lock(); m_converter->convertTo(m_image.image); m_image.image.upsidedown=true; m_image.newimage=true; unlock(); m_grabber->QueueBuffer(Result.Handle(), NULL); } break; case Pylon::Failed: std::cerr << "PYLON: grab failed and "; default: std::cerr << "PYLON: grab returned "<CancelGrab(); return false; } return true; } ///////////////////////////////////////////////////////// // openDevice // ///////////////////////////////////////////////////////// bool videoPYLON :: openDevice(gem::Properties&props) { double d; uint32_t channel=0; if(props.get("channel", d)) channel=d; if(m_camera)closeDevice(); if(NULL==m_factory)return false; Pylon::IPylonDevice *device = NULL; try { if(m_devicename.empty()) { if(m_id2device.empty()) enumerate(); std::map::iterator it=m_id2device.begin(); if(m_devicenum>=0) { std::advance( it, m_devicenum ); } if(it != m_id2device.end()) { device = m_factory->CreateDevice(it->second); } } else { std::map::iterator it=m_id2device.find(m_devicename); if(it!=m_id2device.end()) device = m_factory->CreateDevice(it->second); else device = m_factory->CreateDevice(Pylon::String_t(m_devicename.c_str())); } } catch (GenICam::GenericException &e) { std::cerr << e.GetDescription() << std::endl; return false; } if(device==NULL) return false; try { m_camera=new Pylon::CBaslerGigECamera (device); m_camera->Open(); uint32_t maxchannel=m_camera->GetNumStreamGrabberChannels(); if(channel>maxchannel)channel=maxchannel; m_grabber=new Pylon::CBaslerGigEStreamGrabber(m_camera->GetStreamGrabber(channel)); } catch (GenICam::GenericException &e) { std::cerr << e.GetDescription() << std::endl; close(); return false; } return true; } ///////////////////////////////////////////////////////// // closeDevice // ///////////////////////////////////////////////////////// void videoPYLON :: closeDevice() { if(m_camera){ m_camera->Close(); delete m_camera; } m_camera=NULL; if(m_grabber)delete m_grabber; m_grabber=NULL; } ///////////////////////////////////////////////////////// // startTransfer // ///////////////////////////////////////////////////////// bool videoPYLON :: startTransfer() { if(NULL==m_camera) return false; if(NULL==m_grabber) return false; try { m_grabber->Open(); // Set the image format and AOI // m_camera->PixelFormat.SetValue(Basler_GigECameraParams::PixelFormat_Mono8Signed); // m_camera->OffsetX.SetValue(0); // m_camera->OffsetY.SetValue(0); // m_camera->Width.SetValue(m_camera->Width.GetMax()); // m_camera->Height.SetValue(m_camera->Height.GetMax()); // Set the camera to continuous frame mode /* m_camera->TriggerSelector.SetValue(TriggerSelector_AcquisitionStart); m_camera->TriggerMode.SetValue(TriggerMode_Off); m_camera->AcquisitionMode.SetValue(AcquisitionMode_Continuous); */ // m_camera->ExposureMode.SetValue(ExposureMode_Timed); // m_camera->ExposureTimeRaw.SetValue(100); const size_t ImageSize = (size_t)(m_camera->PayloadSize.GetValue()); m_grabber->MaxBufferSize.SetValue(ImageSize); m_grabber->MaxNumBuffer.SetValue(m_numBuffers); m_grabber->PrepareGrab(); uint32_t i; for (i = 0; i < m_numBuffers; ++i) { CGrabBuffer *pGrabBuffer = new CGrabBuffer(ImageSize); pGrabBuffer->SetBufferHandle(m_grabber->RegisterBuffer( pGrabBuffer->GetBufferPointer(), ImageSize)); // Put the grab buffer object into the buffer list m_buffers.push_back(pGrabBuffer); } std::vector::const_iterator x; for (x=m_buffers.begin(); x != m_buffers.end(); ++x) { // Put buffer into the grab queue for grabbing m_grabber->QueueBuffer((*x)->GetBufferHandle(), NULL); } m_camera->AcquisitionStart.Execute(); } catch (GenICam::GenericException &e) { std::cerr << e.GetDescription() << std::endl; return false; } return true; } ///////////////////////////////////////////////////////// // stopTransfer // ///////////////////////////////////////////////////////// bool videoPYLON :: stopTransfer() { if(m_camera) { // Stop acquisition try { m_camera->AcquisitionStop.Execute(); } catch (GenICam::GenericException &e) { std::cerr << e.GetDescription() << std::endl; } } if(m_grabber) { try { m_grabber->CancelGrab(); // Get all buffers back Pylon::GrabResult r; while(m_grabber->RetrieveResult(r)){;} std::vector::iterator it; for (it = m_buffers.begin(); it != m_buffers.end(); it++) { m_grabber->DeregisterBuffer((*it)->GetBufferHandle()); delete *it; *it = NULL; } m_buffers.clear(); m_grabber->FinishGrab(); m_grabber->Close(); } catch (GenICam::GenericException &e) { std::cerr << e.GetDescription() << std::endl; } } return true; } std::vector videoPYLON::enumerate() { m_id2device.clear(); std::vector result; if(NULL==m_factory)return result; Pylon::DeviceInfoList_t devices; if (0 == m_factory->EnumerateDevices(devices)) { std::cout << "could not enumerate" << std::endl; return result; } if(devices.empty() ) return result; int i=0; for(i=0; i(device); name=gdevice.GetAddress (); if(!name.empty()) { m_id2device[name]=device; SHOWNAME("address")} if(!added && !name.empty()) { result.push_back(name); added=true; } } catch (const std::bad_cast& e) { // std::cerr << i<<" not a GigE&device"<keys; gem::any type; readable.clear(); writeable.clear(); props=gem::pylon::streamgrabberproperties::getKeys(); keys=props.keys(); if(m_grabber) { GenApi::INodeMap*nodes=m_grabber->GetNodeMap(); for(i=0; iGetNode(keys[i].c_str()); if(node) { switch(node->GetAccessMode()) { case GenApi::RO: case GenApi::RW: readable.set(keys[i], props.get(keys[i])); default: break; } } } } else { #if 0 for(i=0; iGetNodeMap(); for(i=0; iGetNode(keys[i].c_str()); if(node) { switch(node->GetAccessMode()) { case GenApi::WO: case GenApi::RW: writeable.set(keys[i], props.get(keys[i])); default: break; } } } } else { #if 0 for(i=0; iGetNodeMap(); for(i=0; iGetNode(keys[i].c_str()); if(node) { switch(node->GetAccessMode()) { case GenApi::RO: case GenApi::RW: readable.set(keys[i], props.get(keys[i])); default: break; } } } } else { #if 0 for(i=0; iGetNodeMap(); for(i=0; iGetNode(keys[i].c_str()); if(node) { switch(node->GetAccessMode()) { case GenApi::WO: case GenApi::RW: writeable.set(keys[i], props.get(keys[i])); default: break; } } } } else { #if 0 for(i=0; iGetDeviceInfo(); Pylon::StringList_t names; di.GetPropertyNames (names); int i=0; for(i=0; ikeys=props.keys(); int i=0; for(i=0; ikeys=props.keys(); int i=0; for(i=0; i