Spinnaker SDK C++
4.3.0.189
 
SaveToVideo.cpp

SaveToVideo.cpp shows how to create a video from a vector of images.It relies on information provided in the Enumeration, Acquisition, and NodeMapInfo examples.

This example introduces the SpinVideo class, which is used to quickly and easily create various types of video files. It demonstrates the creation of four types: uncompressed, MJPG, H264 (AVI) and H264 (MP4).

Please leave us feedback at: https://www.surveymonkey.com/r/TDYMVAPI More source code examples at: https://github.com/Teledyne-MV/Spinnaker-Examples Need help? Check out our forum at: https://teledynevisionsolutions.zendesk.com/hc/en-us/community/topics

//=============================================================================
// Copyright (c) 2025 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved.
//
// This software is the confidential and proprietary information of FLIR
// Integrated Imaging Solutions, Inc. ("Confidential Information"). You
// shall not disclose such Confidential Information and shall use it only in
// accordance with the terms of the license agreement you entered into
// with FLIR Integrated Imaging Solutions, Inc. (FLIR).
//
// FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
// SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES
// SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
// THIS SOFTWARE OR ITS DERIVATIVES.
//=============================================================================
#include "Spinnaker.h"
#include <iostream>
#include <sstream>
#include "SpinVideo.h"
using namespace Spinnaker;
using namespace Spinnaker::GenApi;
using namespace Spinnaker::GenICam;
using namespace Spinnaker::Video;
using namespace std;
const unsigned int numImages = 100; // the number of images to be encoded.
// Use the following enum and global constant to select the type of video
// file to be created and saved.
{
};
// The duration of a video stream depends on the number of encoded images
// and the stream frame rate:
//
// VIDEO_DURATION (second) = NUM_IMAGES / STREAM_FRAME_RATE
//
// eg. NUM_IMAGES = 100 and STREAM_FRAME_RATE = 20fps will result in a
// 5 seconds video stream.
//
// For normal playback speed, STREAM_FRAME_RATE should be set to the
// acquisition frame rate (useCustomFrameRate = false).
// However, the STREAM_FRAME_RATE can be customized (useCustomFrameRate = true,
// and adjusting customFrameRate)
const bool useCustomFrameRate = false;
const float customFrameRate = 1.0;
// This function prepares, saves, and cleans up a video from a vector of images.
int SaveVectorToVideo(INodeMap& nodeMap, INodeMap& nodeMapTLDevice, vector<ImagePtr>& images)
{
int result = 0;
cout << endl << endl << "*** CREATING VIDEO ***" << endl << endl;
try
{
// Retrieve device serial number for filename
string deviceSerialNumber = "";
CStringPtr ptrStringSerial = nodeMapTLDevice.GetNode("DeviceSerialNumber");
if (IsReadable(ptrStringSerial))
{
deviceSerialNumber = ptrStringSerial->GetValue();
cout << "Device serial number retrieved as " << deviceSerialNumber << "..." << endl;
}
//
// Get the current frame rate; acquisition frame rate recorded in hertz
//
// *** NOTES ***
// The video frame rate can be set to anything; however, in order to
// have videos play in real-time, the acquisition frame rate can be
// retrieved from the camera.
//
CFloatPtr ptrAcquisitionFrameRate = nodeMap.GetNode("AcquisitionFrameRate");
if (!IsReadable(ptrAcquisitionFrameRate))
{
cout << "Unable to retrieve frame rate. Aborting..." << endl << endl;
return -1;
}
float frameRateToSet = static_cast<float>(ptrAcquisitionFrameRate->GetValue());
{
frameRateToSet = customFrameRate;
}
cout << "Frame rate to be set to " << frameRateToSet << "..." << endl;
//
// Create a unique filename
//
// *** NOTES ***
// This example creates filenames according to the type of video
// being created. Notice that '.avi' does not need to be appended to the
// name of the file. This is because the SpinVideo object takes care
// of the file extension automatically.
//
string videoFilename;
{
videoFilename = "SaveToVideo-Uncompressed";
if (deviceSerialNumber != "")
{
videoFilename = videoFilename + "-" + deviceSerialNumber.c_str();
}
break;
case MJPG:
videoFilename = "SaveToVideo-MJPG";
if (deviceSerialNumber != "")
{
videoFilename = videoFilename + "-" + deviceSerialNumber.c_str();
}
break;
case H264_AVI:
case H264_MP4:
videoFilename = "SaveToVideo-H264";
if (deviceSerialNumber != "")
{
videoFilename = videoFilename + "-" + deviceSerialNumber.c_str();
}
}
//
// Select option and open video file type
//
// *** NOTES ***
// Depending on the file type, a number of settings need to be set in
// an object called an option. An uncompressed option only needs to
// have the video frame rate set whereas videos with MJPG or H264
// compressions should have more values set.
//
// Once the desired option object is configured, open the video file
// with the option in order to create the video file.
//
// *** LATER ***
// Once all images have been added, it is important to close the file -
// this is similar to many other standard file streams.
//
SpinVideo video;
// Set maximum video file size to 2GB.
// A new video file is generated when 2GB
// limit is reached. Setting maximum file
// size to 0 indicates no limit.
// Note that this limit serves only as a hint and can still be slightly exceeded
// in some cases after the video trailer has been written.
const unsigned int k_videoFileSize = 2048;
video.SetMaximumFileSize(k_videoFileSize);
{
option.frameRate = frameRateToSet;
option.height = static_cast<unsigned int>(images[0]->GetHeight());
option.width = static_cast<unsigned int>(images[0]->GetWidth());
video.Open(videoFilename.c_str(), option);
}
{
option.frameRate = frameRateToSet;
option.quality = 75;
option.height = static_cast<unsigned int>(images[0]->GetHeight());
option.width = static_cast<unsigned int>(images[0]->GetWidth());
video.Open(videoFilename.c_str(), option);
}
{
option.frameRate = frameRateToSet;
option.bitrate = 1000000;
option.height = static_cast<unsigned int>(images[0]->GetHeight());
option.width = static_cast<unsigned int>(images[0]->GetWidth());
// Set this to true to save to a mp4 container
// Decrease this for a higher quality
option.crf = 23;
video.Open(videoFilename.c_str(), option);
}
//
// Construct and save video
//
// *** NOTES ***
// Although the video file has been opened, images must be individually
// appended in order to construct the video.
//
cout << "Appending " << images.size() << " images to video file: " << videoFilename << endl
<< endl;
for (unsigned int imageCnt = 0; imageCnt < images.size(); imageCnt++)
{
video.Append(images[imageCnt]);
cout << "\tAppended image " << imageCnt << "..." << endl;
}
//
// Close video file
//
// *** NOTES ***
// Once all images have been appended, it is important to close the
// video file. Notice that once a video file has been closed, no more
// images can be added.
//
video.Close();
cout << endl << "Video saved at " << videoFilename << endl << endl;
}
{
cout << "Error: " << e.what() << endl;
result = -1;
}
return result;
}
// This function prints the device information of the camera from the transport
// layer; please see NodeMapInfo example for more in-depth comments on printing
// device information from the nodemap.
{
int result = 0;
cout << endl << "*** DEVICE INFORMATION ***" << endl << endl;
try
{
FeatureList_t features;
CCategoryPtr category = nodeMap.GetNode("DeviceInformation");
if (IsReadable(category))
{
category->GetFeatures(features);
FeatureList_t::const_iterator it;
for (it = features.begin(); it != features.end(); ++it)
{
try
{
CNodePtr pfeatureNode = *it;
cout << pfeatureNode->GetName() << " : ";
CValuePtr pValue = (CValuePtr)pfeatureNode;
cout << (IsReadable(pValue) ? pValue->ToString() : "Node not readable");
cout << endl;
}
{
cout << "Node not readable" << endl;
}
}
}
else
{
cout << "Device control information not readable." << endl;
}
}
{
cout << "Error: " << e.what() << endl;
result = -1;
}
return result;
}
// This function acquires and saves 30 images from a device; please see
// Acquisition example for more in-depth comments on acquiring images.
int AcquireImages(CameraPtr pCam, INodeMap& nodeMap, vector<ImagePtr>& images)
{
int result = 0;
cout << endl << endl << "*** IMAGE ACQUISITION ***" << endl << endl;
try
{
// Set acquisition mode to continuous
CEnumerationPtr ptrAcquisitionMode = nodeMap.GetNode("AcquisitionMode");
if (!IsReadable(ptrAcquisitionMode) ||
!IsWritable(ptrAcquisitionMode))
{
cout << "Unable to get or set acquisition mode to continuous (node retrieval). Aborting..." << endl << endl;
return -1;
}
CEnumEntryPtr ptrAcquisitionModeContinuous = ptrAcquisitionMode->GetEntryByName("Continuous");
if (!IsReadable(ptrAcquisitionModeContinuous))
{
cout << "Unable to get acquisition mode to continuous (entry 'continuous' retrieval). Aborting..." << endl
<< endl;
return -1;
}
int64_t acquisitionModeContinuous = ptrAcquisitionModeContinuous->GetValue();
ptrAcquisitionMode->SetIntValue(acquisitionModeContinuous);
cout << "Acquisition mode set to continuous..." << endl;
// Begin acquiring images
pCam->BeginAcquisition();
cout << "Acquiring images..." << endl << endl;
// Retrieve and convert images
//
// Create ImageProcessor instance for post processing images
//
ImageProcessor processor;
//
// Set default image processor color processing method
//
// *** NOTES ***
// By default, if no specific color processing algorithm is set, the image
// processor will default to NEAREST_NEIGHBOR method.
//
for (unsigned int imageCnt = 0; imageCnt < numImages; imageCnt++)
{
try
{
// Retrieve the next received image
ImagePtr pResultImage = pCam->GetNextImage(1000);
if (pResultImage->IsIncomplete())
{
cout << "Image incomplete with image status " << pResultImage->GetImageStatus() << "..." << endl
<< endl;
}
else
{
cout << "Grabbed image " << imageCnt << ", width = " << pResultImage->GetWidth()
<< ", height = " << pResultImage->GetHeight() << endl;
// Deep copy image into image vector
images.push_back(processor.Convert(pResultImage, PixelFormat_Mono8));
}
// Release image
pResultImage->Release();
}
{
cout << "Error: " << e.what() << endl;
result = -1;
}
}
// End acquisition
pCam->EndAcquisition();
}
{
cout << "Error: " << e.what() << endl;
result = -1;
}
return result;
}
// This function acts as the body of the example; please see NodeMapInfo example
// for more in-depth comments on setting up cameras.
{
int result = 0;
int err = 0;
try
{
// Retrieve TL device nodemap and print device information
INodeMap& nodeMapTLDevice = pCam->GetTLDeviceNodeMap();
result = PrintDeviceInfo(nodeMapTLDevice);
// Initialize camera
pCam->Init();
// Retrieve GenICam nodemap
INodeMap& nodeMap = pCam->GetNodeMap();
// Acquire images and save into vector
vector<ImagePtr> images;
err = AcquireImages(pCam, nodeMap, images);
if (err < 0)
{
return err;
}
// Save vector of images to video
result = result | SaveVectorToVideo(nodeMap, nodeMapTLDevice, images);
// Deinitialize camera
pCam->DeInit();
}
{
cout << "Error: " << e.what() << endl;
result = -1;
}
return result;
}
// Example entry point; please see Enumeration example for more in-depth
// comments on preparing and cleaning up the system.
int main(int /*argc*/, char** /*argv*/)
{
int result = 0;
// Print application build information
cout << "Application build date: " << __DATE__ << " " << __TIME__ << endl << endl;
// Retrieve singleton reference to system object
// Print out current library version
const LibraryVersion spinnakerLibraryVersion = system->GetLibraryVersion();
cout << "Spinnaker library version: " << spinnakerLibraryVersion.major << "." << spinnakerLibraryVersion.minor
<< "." << spinnakerLibraryVersion.type << "." << spinnakerLibraryVersion.build << endl
<< endl;
// Retrieve list of cameras from the system
CameraList camList = system->GetCameras();
unsigned int numCameras = camList.GetSize();
cout << "Number of cameras detected: " << numCameras << endl << endl;
// Finish if there are no cameras
if (numCameras == 0)
{
// Clear camera list before releasing system
camList.Clear();
// Release system
system->ReleaseInstance();
cout << "Not enough cameras!" << endl;
cout << "Done! Press Enter to exit..." << endl;
getchar();
return -1;
}
// Run example on each camera
for (unsigned int i = 0; i < numCameras; i++)
{
cout << endl << "Running example for camera " << i << "..." << endl;
result = result | RunSingleCamera(camList.GetByIndex(i));
cout << "Camera " << i << " example complete..." << endl << endl;
}
// Clear camera list before releasing system
camList.Clear();
// Release system
system->ReleaseInstance();
cout << endl << "Done! Press Enter to exit..." << endl;
getchar();
return result;
}
useCustomFrameRate
const bool useCustomFrameRate
Definition: SaveToVideo.cpp:72
Spinnaker
Definition: BasePtr.h:23
Spinnaker::GenICam
Definition: GCString.h:30
Spinnaker::CameraList
Used to hold a list of camera objects.
Definition: CameraList.h:41
Spinnaker::Video
Definition: SpinVideo.h:27
Spinnaker.h
Spinnaker::CameraList::Clear
void Clear()
Clears the list of cameras and destroys their corresponding reference counted objects.
Spinnaker::GenApi::CValuePtr
CPointer< IValue > CValuePtr
SmartPointer for IValue interface pointer.
Definition: Pointer.h:317
Spinnaker::GenApi::INodeMap
interface SPINNAKER_API_ABSTRACT INodeMap
Interface to access the node map.
Definition: INodeMap.h:54
SpinVideo.h
RunSingleCamera
int RunSingleCamera(CameraPtr pCam)
Definition: SaveToVideo.cpp:406
Spinnaker::Video::SpinVideo
Provides the functionality for the user to record images to an AVI/MP4 file.
Definition: SpinVideo.h:43
Spinnaker::GenApi
Definition: AutoPollController.h:32
SpinnakerGenApi.h
Spinnaker::LibraryVersion::minor
unsigned int minor
Minor version of the library.
Definition: SpinnakerDefs.h:711
Spinnaker::LibraryVersion::build
unsigned int build
Build number of the library.
Definition: SpinnakerDefs.h:717
Spinnaker::GenApi::CPointer
Encapsulates a GenApi pointer dealing with the dynamic_cast automatically.
Definition: Pointer.h:74
Spinnaker::LibraryVersion::type
unsigned int type
Version type of the library.
Definition: SpinnakerDefs.h:714
Spinnaker::Video::SpinVideo::SetMaximumFileSize
virtual void SetMaximumFileSize(unsigned int size)
Set the maximum file size (in megabytes) of a AVI/MP4 file.
Spinnaker::Video::MJPGOption
Definition: SpinVideoDefs.h:46
main
int main(int, char **)
Definition: SaveToVideo.cpp:450
customFrameRate
const float customFrameRate
Definition: SaveToVideo.cpp:73
Spinnaker::PixelFormat_Mono8
@ PixelFormat_Mono8
Definition: CameraDefs.h:731
UNCOMPRESSED
@ UNCOMPRESSED
Definition: SaveToVideo.cpp:52
Spinnaker::Video::SpinVideo::Open
virtual void Open(const char *pFileName, AVIOption &pOption)
Open an video file in preparation for writing Images to disk.
Spinnaker::Video::SpinVideo::Append
virtual void Append(ImagePtr pImage)
Append an image to the video file.
Spinnaker::Video::AVIOption
Definition: SpinVideoDefs.h:116
Spinnaker::CameraList::GetSize
unsigned int GetSize() const
Returns the size of the camera list.
Spinnaker::SystemPtr
A reference tracked pointer to a system object.
Definition: SystemPtr.h:43
Spinnaker::ImageProcessor
Image post processing class for converting a source image to another pixel format.
Definition: ImageProcessor.h:159
Spinnaker::ImageProcessor::SetColorProcessing
void SetColorProcessing(ColorProcessingAlgorithm colorAlgorithm)
Sets the color processing algorithm used at the time of the Convert() call, therefore the most recent...
Spinnaker::Exception::what
virtual const char * what() const
virtual override for what().
Spinnaker::System::GetInstance
static SystemPtr GetInstance()
Returns a pointer to a Singleton instance of a System object.
MJPG
@ MJPG
Definition: SaveToVideo.cpp:53
Spinnaker::ImagePtr
A reference tracked pointer to an image object.
Definition: ImagePtr.h:45
Spinnaker::CameraPtr
A reference tracked pointer to a camera object.
Definition: CameraPtr.h:43
Spinnaker::Video::SpinVideo::Close
virtual void Close()
Close the video file.
Spinnaker::GenApi::IsWritable
bool IsWritable(EAccessMode AccessMode)
Tests if writable.
Definition: INode.h:277
Spinnaker::Exception
The Exception object represents an error that is returned from the library.
Definition: Exception.h:50
option
Definition: Getopt.h:150
Spinnaker::GenApi::CFloatPtr
SmartPointer for IFloat interface pointer.
Definition: Pointer.h:420
H264_MP4
@ H264_MP4
Definition: SaveToVideo.cpp:55
Spinnaker::SPINNAKER_COLOR_PROCESSING_ALGORITHM_HQ_LINEAR
@ SPINNAKER_COLOR_PROCESSING_ALGORITHM_HQ_LINEAR
Well-balanced speed and quality.
Definition: SpinnakerDefs.h:189
PrintDeviceInfo
int PrintDeviceInfo(INodeMap &nodeMap)
Definition: SaveToVideo.cpp:264
Spinnaker::GenApi::IsReadable
bool IsReadable(EAccessMode AccessMode)
Tests if readable.
Definition: INode.h:253
numImages
const unsigned int numImages
Definition: SaveToVideo.cpp:46
Spinnaker::Video::H264Option
Definition: SpinVideoDefs.h:76
chosenVideoFileType
const videoFileType chosenVideoFileType
Definition: SaveToVideo.cpp:58
Spinnaker::ImageProcessor::Convert
ImagePtr Convert(const ImagePtr &srcImage, PixelFormatEnums destFormat) const
Converts the source image buffer to the specified destination pixel format and returns the result in ...
videoFileType
videoFileType
Definition: SaveToVideo.cpp:50
AcquireImages
int AcquireImages(CameraPtr pCam, INodeMap &nodeMap, vector< ImagePtr > &images)
Definition: SaveToVideo.cpp:310
Spinnaker::CameraList::GetByIndex
CameraPtr GetByIndex(unsigned int index) const
Returns a pointer to a camera object at the "index".
SaveVectorToVideo
int SaveVectorToVideo(INodeMap &nodeMap, INodeMap &nodeMapTLDevice, vector< ImagePtr > &images)
Definition: SaveToVideo.cpp:76
H264_AVI
@ H264_AVI
Definition: SaveToVideo.cpp:54
Spinnaker::LibraryVersion
Provides easier access to the current version of Spinnaker.
Definition: SpinnakerDefs.h:705
Spinnaker::LibraryVersion::major
unsigned int major
Major version of the library.
Definition: SpinnakerDefs.h:708