bool AcquireImages(CamInfo* cams, int numCams) { int i; PvResult result; // Initialize Camera System PvSystem system; system.SetDetectionTimeout(2000); result = system.Find(); if(!result.IsOK()){ printf("PvSystem::Find Error: %s", result.GetCodeString().GetAscii()); return false; } PvDevice lDevice[numCams]; PvGenParameterArray *lDeviceParams[numCams]; PvStream lStream[numCams]; PvPipeline *lPipeline[numCams]; for(i=0; i < numCams; i++){ PvDeviceInfo* lDeviceInfo = NULL; PvDeviceInfo* tempInfo; // Get the number of GEV Interfaces that were found using GetInterfaceCount. PvUInt32 lInterfaceCount = system.GetInterfaceCount(); // For each interface, check MAC Address against passed address for( PvUInt32 x = 0; x < lInterfaceCount; x++ ) { // get pointer to each of interface PvInterface * lInterface = system.GetInterface( x ); // Get the number of GEV devices that were found using GetDeviceCount. PvUInt32 lDeviceCount = lInterface->GetDeviceCount(); for( PvUInt32 y = 0; y < lDeviceCount ; y++ ) { tempInfo = lInterface->GetDeviceInfo( y ); if(strlen(cams[i].MACAddress) == strlen(tempInfo->GetMACAddress().GetAscii()) && strncmp(cams[i].MACAddress,tempInfo->GetMACAddress().GetAscii(),strlen(cams[i].MACAddress)) == 0){ lDeviceInfo = tempInfo; break; } } } // If no device is selected, abort if( lDeviceInfo == NULL ) { printf( "No device selected.\n" ); return false; } // Connect to the GEV Device printf( "Connecting to %s\n", lDeviceInfo->GetMACAddress().GetAscii() ); if ( !lDevice[i].Connect( lDeviceInfo ).IsOK() ) { printf( "Unable to connect to %s\n", lDeviceInfo->GetMACAddress().GetAscii() ); return false; } printf( "Successfully connected to %s\n", lDeviceInfo->GetMACAddress().GetAscii() ); printf( "\n" ); // Get device parameters need to control streaming lDeviceParams[i] = lDevice[i].GetGenParameters(); // Negotiate streaming packet size lDevice[i].NegotiatePacketSize(); // Open stream - have the PvDevice do it for us printf( "Opening stream to device\n" ); lStream[i].Open( lDeviceInfo->GetIPAddress() ); // Create the PvPipeline object lPipeline[i] = new PvPipeline( &lStream[i] ); // Reading payload size from device PvInt64 lSize = 0; lDeviceParams[i]->GetIntegerValue( "PayloadSize", lSize ); // Set the Buffer size and the Buffer count lPipeline[i]->SetBufferSize( static_cast<PvUInt32>( lSize ) ); lPipeline[i]->SetBufferCount( 16 ); // Increase for high frame rate without missing block IDs // Have to set the Device IP destination to the Stream lDevice[i].SetStreamDestination( lStream[i].GetLocalIPAddress(), lStream[i].GetLocalPort() ); } PvGenParameterArray *lStreamParams[numCams]; for(i=0; i < numCams; i++){ // IMPORTANT: the pipeline needs to be "armed", or started before // we instruct the device to send us images printf( "Starting pipeline %d\n",i); lPipeline[i]->Start(); // Get stream parameters/stats lStreamParams[i] = lStream[i].GetParameters(); // TLParamsLocked is optional but when present, it MUST be set to 1 // before sending the AcquisitionStart command lDeviceParams[i]->SetIntegerValue( "TLParamsLocked", 1 ); printf( "Resetting timestamp counter...\n" ); lDeviceParams[i]->ExecuteCommand( "GevTimestampControlReset" ); // The pipeline is already "armed", we just have to tell the device // to start sending us images printf( "Sending StartAcquisition command to device\n" ); lDeviceParams[i]->ExecuteCommand( "AcquisitionStart" ); } char lDoodle[] = "|\\-|-/"; int lDoodleIndex = 0; PvInt64 lImageCountVal = 0; double lFrameRateVal = 0.0; double lBandwidthVal = 0.0; PvInt64 lPipelineBlocksDropped = 0; // Acquire images until the user instructs us to stop printf( "\n<press the enter key to stop streaming>\n" ); //PvBufferWriter writer; char filePath[MAXFILEPATH]; PvUInt32 lWidth = 4096, lHeight = 9250; while ( running ) { for(i=0; i < numCams; i++){ // Retrieve next buffer PvBuffer *lBuffer = NULL; PvResult lOperationResult; PvResult lResult = lPipeline[i]->RetrieveNextBuffer( &lBuffer, 1000, &lOperationResult ); if ( lResult.IsOK() ) { if ( lOperationResult.IsOK() ) { lStreamParams[i]->GetIntegerValue( "ImagesCount", lImageCountVal ); lStreamParams[i]->GetFloatValue( "AcquisitionRateAverage", lFrameRateVal ); lStreamParams[i]->GetFloatValue( "BandwidthAverage", lBandwidthVal ); lStreamParams[i]->GetIntegerValue("PipelineBlocksDropped", lPipelineBlocksDropped); filePath[0] = '\0'; sprintf(filePath,"%s/%s%04X.tif",cams[i].filename,cams[i].prefix,lBuffer->GetBlockID()); TIFF *out = TIFFOpen(filePath,"w"); TIFFSetField(out, TIFFTAG_IMAGEWIDTH, lWidth); TIFFSetField(out, TIFFTAG_IMAGELENGTH, lHeight); TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, 1); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); TIFFSetField(out, TIFFTAG_COMPRESSION, COMPRESSION_NONE); TIFFWriteEncodedStrip(out,0,lBuffer->GetDataPointer(),lWidth*lHeight); TIFFClose(out); printf( "%d:%s%c Timestamp: %016llX BlockID: %04X %.01f FPS %d DROP %.01f Mb/s\r\n",i, cams[i].prefix, lDoodle[ lDoodleIndex ], lBuffer->GetTimestamp(), lBuffer->GetBlockID(), lFrameRateVal, lPipelineBlocksDropped, lBandwidthVal / 1000000.0 ); } else { printf("%d: ERROR Code: %s, Description: %s\r\n",i,lOperationResult.GetCodeString().GetAscii(),lOperationResult.GetDescription().GetAscii()); } // We have an image - do some processing (...) // VERY IMPORTANT: // release the buffer back to the pipeline lPipeline[i]->ReleaseBuffer( lBuffer ); usleep(200); } else { // Timeout printf( "%d:%s%c Timeout\r\n",i, cams[i].prefix,lDoodle[ lDoodleIndex ]); } } ++lDoodleIndex %= 6; } //_getch(); // Flush key buffer for next stop printf( "\n\n" ); for(i=0; i < numCams; i++){ // Tell the device to stop sending images printf( "Sending AcquisitionStop command to the device\n" ); lDeviceParams[i]->ExecuteCommand( "AcquisitionStop" ); // If present reset TLParamsLocked to 0. Must be done AFTER the // streaming has been stopped lDeviceParams[i]->SetIntegerValue( "TLParamsLocked", 0 ); // We stop the pipeline - letting the object lapse out of // scope would have had the destructor do the same, but we do it anyway printf( "Stop pipeline\n" ); lPipeline[i]->Stop(); delete lPipeline[i]; // Now close the stream. Also optionnal but nice to have printf( "Closing stream\n" ); lStream[i].Close(); // Finally disconnect the device. Optional, still nice to have printf( "Disconnecting device\n" ); lDevice[i].Disconnect(); } return true; }
int main( int aCount, const char ** aArgs ) { // Creates default configuration, parse command line parameters Config lConfig; lConfig.ParseCommandLine( aCount, aArgs ); // Create video source (pattern generator) VideoSource lSource; // Get video source properties PvUInt32 lWidth = lConfig.GetWidth(); PvUInt32 lHeight = lConfig.GetHeight(); PvPixelType lPixelFormat = PvPixelMono8; PvUInt32 lSize = lWidth * lHeight; // Allocate transmit buffers PvBufferList lBuffers; PvBufferList lFreeBuffers; for ( PvUInt32 i = 0; i < lConfig.GetBufferCount(); i++ ) { // Alloc new buffer PvBuffer *lBuffer = new PvBuffer(); lBuffer->GetImage()->Alloc( lWidth, lHeight, lPixelFormat ); // Set to 0 memset( lBuffer->GetDataPointer(), 0x00, lSize ); // Add to both buffer list and free buffer list lBuffers.push_back( lBuffer ); lFreeBuffers.push_back( lBuffer ); } // Create transmitter, set packet size PvTransmitterRaw lTransmitter; lTransmitter.SetPacketSize( lConfig.GetPacketSize() ); // Create virtual device (used for discovery) PvVirtualDevice lDevice; lDevice.StartListening( lConfig.GetSourceAddress() ); cout << "Listening for device discovery requests on " << lConfig.GetSourceAddress() << endl; // Open transmitter - sets destination and source PvResult lResult = lTransmitter.Open( lConfig.GetDestinationAddress(), lConfig.GetDestinationPort(), lConfig.GetSourceAddress(), lConfig.GetSourcePort() ); if ( !lResult.IsOK() ) { cout << "Failed to open a connection to the transmitter." << endl; return 1; } cout << "Transmission stream opened:" << endl; cout << "Source: " << lTransmitter.GetSourceIPAddress().GetAscii() << " port " << lTransmitter.GetSourcePort() << endl; cout << "Destination: " << lConfig.GetDestinationAddress() << " port " << lConfig.GetDestinationPort() << endl; if ( !lConfig.GetSilent() ) { cout << "Press any key to begin transmitting.\r"; PvWaitForKeyPress(); } cout << "Press any key to stop transmitting." << endl; // Set maximum throughput (just to even out traffic, as we control throughput at the source) if ( lConfig.GetFPS() != 0 ) { // Multiply image size (in bits) by FPS float lMax = static_cast<float>( lSize ) * 8; lMax *= lConfig.GetFPS(); // Since we control throughput at the source, make sure maximum throughput is slightly // higher than what we need. We want to even out packet traffic, not slow down source frame rate lMax *= 1.1f; // Set max throughput lTransmitter.SetMaxPayloadThroughput( lMax ); } char lDoodle[] = "|\\-|-/"; int lDoodleIndex = 0; // Reset transmitter stats lTransmitter.ResetStats(); // Used to transmit at a steady frame rate PvFPSStabilizer lStabilizer; // Acquisition/transmission loop while( !PvKbHit() ) { // Step 1: If timing is right to meet desired FPS, generate pattern, transmit if ( ( lConfig.GetFPS() == 0 ) || lStabilizer.IsTimeToDisplay( (PvUInt32)lConfig.GetFPS() ) ) { // Are there buffers available for transmission? if ( lFreeBuffers.size() > 0 ) { // Retrieve buffer from list PvBuffer *lBuffer = lFreeBuffers.front(); lFreeBuffers.pop_front(); // Generate the test pattern (if needed) if ( !lConfig.GetNoPattern() ) { lSource.CopyPattern( lBuffer ); } // Queue the buffer for transmission lTransmitter.QueueBuffer( lBuffer ); } } // Step 2: Retrieve free buffer(s), display stats and requeue PvBuffer *lBuffer = NULL; while ( lTransmitter.RetrieveFreeBuffer( &lBuffer, 0 ).IsOK() ) { // Queue buffers back in available buffer list lFreeBuffers.push_back( lBuffer ); // Buffer transmission complete, dislay stats cout << fixed << setprecision( 1 ); cout << lDoodle[ lDoodleIndex ] << " "; cout << "Transmitted " << lTransmitter.GetBlocksTransmitted() << " blocks "; cout << "at " << lTransmitter.GetAverageTransmissionRate() << " "; cout << "(" << lTransmitter.GetInstantaneousTransmissionRate() << ") FPS "; cout << lTransmitter.GetAveragePayloadThroughput() / 1000000.0f << " "; cout << "(" << lTransmitter.GetInstantaneousPayloadThroughput() / 1000000.0f << ") Mb/s \r"; ++lDoodleIndex %= 6; } } // Close transmitter (will also abort buffers) lTransmitter.Close(); // Free buffers PvBufferList::iterator lIt = lBuffers.begin(); while ( lIt != lBuffers.end() ) { delete ( *lIt ); lIt++; } // Stop virtual device lDevice.StopListening(); }