This example demonstrates how to write a sequence of images to a video file.
The program can be found in the %TOPLEVEL%\Samples\VC\CreateVideoFile directory. In order to run the program, open the solution file CreateVideoFile.sln in this directory and select Build -> Build CreateVideoFile in the menu. You can execute the program by selecting Debug -> Start.
The program generates a list of all available media stream containers and prompts the end user to select one. In a second step, the end user may choose between 3 possible ways of storing the video data in the file:
In the next step, the program asks for a filename. Once the end user has entered a file name, the program waits until another key is pressed. Then, it starts capturing. It proceeds to capture, writing data into the video file, until enter is pressed.
The example program uses the setupDeviceFromFile function from %TOPLEVEL%\Samples\VC\Common\CmdHelper.h. This function displays the device selection dialog and saves the selected device in a configuration file. When the function is called again, this configuration file is reloaded.
Grabber grabber; if( !setupDeviceFromFile( grabber ) ) { return 1; }
the end user may choose between 3 possible ways to store the video data in the file:
In order to save image data to a video file, a MediaStreamSink is created and initialized.
// This will contain available codecs/uncompressed formats for this container std::vector<codec_entry> codecList; tCodecList avCodecList = Codec::getAvailableCodecList(); for( tCodecList::iterator it = avCodecList.begin(); it != avCodecList.end(); ++it ) { tCodecPtr pcodec = *it; // Only add Codecs the container supports if( pCont->isCustomCodecSupported( pcodec ) ) { codecList.push_back( codec_entry( pcodec->getName(), pcodec, GUID_NULL ) ); } } // Only add uncompressed types when the container supports that if( pCont->isUncompressedSupported() ) { codecList.push_back( codec_entry( "Uncompressed RGB32", nullptr, MEDIASUBTYPE_RGB32 ) ); codecList.push_back( codec_entry( "Uncompressed RGB24", nullptr, MEDIASUBTYPE_RGB24 ) ); codecList.push_back( codec_entry( "Uncompressed Y800", nullptr, MEDIASUBTYPE_Y800 ) ); codecList.push_back( codec_entry( "Uncompressed UYVY", nullptr, MEDIASUBTYPE_UYVY ) ); } if( codecList.empty() ) { // there are no entries in the codec list, so just create a sink only containing the container return MediaStreamSink::create( pCont ); } codecList.insert( codecList.begin(), codec_entry( "No codec", nullptr, GUID_NULL ) ); int idx = presentUserChoice( codecList ); if( idx == -1 ) { std::cerr << "No choice was made from the codec list." << std::endl; return nullptr; } codec_entry choice = codecList.at(idx); if( choice.codec == NULL ) { // The user chose a uncompressed type return MediaStreamSink::create( pCont, choice.uncompressed_subtype ); } // The user chose a codec. // Open the dialog if available and then create the according sink using codec and container if( choice.codec->hasDialog() ) { std::cout << "Setup the codec: " << std::endl; choice.codec->callDialog(); } // Create the sink with the specified codec. return MediaStreamSink::create( pCont, choice.codec );
In order to save image data to a video file, a MediaStreamSink is created and initialized to record an AVI files. The selected codec and filename are set. The sink is initially paused by calling GrabberSinkType::setSinkMode with the parameter ePAUSE.
// The sink is initially paused, so that no video data is written to the file. pSink->setSinkMode( GrabberSinkType::ePAUSE ); // apply the sink grabber.setSinkType( pSink ); // Start the live mode. The live video will be displayed but no images will be written // to the AVI file because pSink is in pause mode. if( !grabber.startLive( true ) ) { std::cerr << grabber.getLastError().toString() << std::endl; return -1; } fflush(stdin); std::cout << "Press [enter] to start capturing!"; std::cin.get(); // Start the sink. The image stream is written to the AVI file. pSink->setSinkMode(GrabberSinkType::eRUN ); std::cout << "Video recording started." << std::endl; std::cout << "Press [enter] to stop capturing!"; std::cin.get(); // Stop the live mode. This stops writing the avi file to disk. grabber.stopLive();
After live mode has been started using Grabber::startLive, the program waits for end user input. To actually start AVI recording, the sink is put in run mode.