Writing an Image Stream to a video file

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.

Opening a Device

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;
}

Selecting the video data format

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 );

Controlling Video Recording

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.

See also

Properties of a Codec

<< Programmer's Guide