Saving Codec Properties

This chapter shows you how to handle codecs and how to save and load the properties of a codec.

Introduction

The source code for this example is contained in the samples\VB71\Saving Codec Properties and samples\C#\Saving Codec Properties sample source directory.

A codec compresses and decompresses video streams. Sometimes, a codec is also referred to as a "compressor" or an "avicompressor".

The properties of some (but not all) codecs can be retrieved and assigned with IC Imaging Control. For example, the quality of a video stream may be set before it is saved.

Codec properties are supplied as a binary data stream. It is very important to know the length of the data stream, as later when an application loads the data stream, it is required to allocate memory for it.

The saving file format must be binary, because the data stream is also binary.

You should not alter the binary data stream from a codec. Doing so would make the data no longer fit the codec, thus causing unpredictable errors. Furthermore, the codec properties of one codec will not match each other. IC Imaging Control prevents this situation from happening at all - it causes an error message.

A codec is an external DLL file that is handled by an AviCompressor object. If an AviCompressor object becomes invalid, the DLL will be removed from memory. In this case, most codecs will loose their previously set properties. You should, therefore, declare a global AviCompressor object in your form in order to avoid loosing properties.

You can retrieve data from or assign data to codecs where the property PropertyPageAvailable is True. It is therefore necessary to check this property before performing an operation.

Setting up the Project

Create a new project and add IC Imaging Control to the form. Now add 3 buttons to the form and label them Save Data, Load Data and Show Property Page. Name the buttons cmdSaveData, cmdLoadData and cmdShowPropertyPage respectively. Add at least one combo box to the form and name it cboVideoCodec. This combo box will contain the names of the codecs.

image

Setting Up the Codec

First of all, an application needs a global AviCompressor object that contains the data of the codec. This must be global, because the AviCompressor 's properties will be lost when it is removed from memory. So add the following line to the beginning of the form:

[VB.NET]
Dim Codec As TIS.Imaging.AviCompressor
[C#]
private TIS.Imaging.AviCompressor Codec;

Add a Form_Load event procedure to the form and enter the following code to fill the combo box with the available codecs:

[VB.NET]
Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles MyBase.Load     'Insert all installed codecs into the cboVideoCodec combobox.     For Each Codec As TIS.Imaging.AviCompressor In IcImagingControl1.AviCompressors         cboVideoCodec.Items.Add(Codec)     Next     ' Show the first codec in the combobox.     cboVideoCodec.SelectedIndex = 0       Codec = CType(cboVideoCodec.SelectedItem(), TIS.Imaging.AviCompressor)       ' Enable or disable the buttons.     cmdShowPropertyPage.Enabled = Codec.PropertyPageAvailable     cmdLoadData.Enabled = Codec.PropertyPageAvailable     cmdSaveData.Enabled = Codec.PropertyPageAvailable End Sub
[C#]
private void Form1_Load(object sender, System.EventArgs e) {     // Insert all installed codecs into the cboVideoCodec combobox.     foreach( TIS.Imaging.AviCompressor _Codec in  icImagingControl1.AviCompressors)     {         cboVideoCodec.Items.Add(_Codec);     }     // Show the first codec in the combobox.     cboVideoCodec.SelectedIndex = 0;       Codec = (TIS.Imaging.AviCompressor)cboVideoCodec.SelectedItem;       // Enable or disable the buttons.     cmdShowPropertyPage.Enabled = Codec.PropertyPageAvailable;     cmdLoadData.Enabled = Codec.PropertyPageAvailable;     cmdSaveData.Enabled = Codec.PropertyPageAvailable; }

This code uses the AviCompressors property of IC Imaging Control to generate a list of all available codecs. As you can see, the global variable Codec is used as item in the For Each .. In .. statement. The first available codec will be assigned to the global AviCompressor object Codec. The three buttons will be enabled or disabled according to the property PropertyPageAvailable in the AviCompressor object. This avoids performing operations that are not supported by the codec.

Now add the SelectedValueChanged event procedure of the combo box cboVideoCodec to your form:

[VB.NET]
Private Sub cboVideoCodec_SelectedValueChanged(ByVal sender As ObjectByVal e As System.EventArgs) Handles cboVideoCodec.SelectedValueChanged     Codec = CType(cboVideoCodec.SelectedItem(), TIS.Imaging.AviCompressor)       ' Enable or disable the buttons.     cmdShowPropertyPage.Enabled = Codec.PropertyPageAvailable     cmdLoadData.Enabled = Codec.PropertyPageAvailable     cmdSaveData.Enabled = Codec.PropertyPageAvailable End Sub
[C#]
private void cboVideoCodec_SelectedIndexChanged(object sender, System.EventArgs e) {     Codec = (TIS.Imaging.AviCompressor)cboVideoCodec.SelectedItem;             // Enable or disable the buttons.     cmdShowPropertyPage.Enabled = Codec.PropertyPageAvailable;     cmdLoadData.Enabled = Codec.PropertyPageAvailable;     cmdSaveData.Enabled = Codec.PropertyPageAvailable; }

The selected item of the combo box refers to an AviCompressor object. This item is assigned to the global AviCompressor object Codec.

The AviCompressor 's property PropertyPageAvailable is used to disable or enable the buttons. This prevents, for example, the user from pressing the cmdShowPropertyPage button when no property dialog is available for the codec.

Now, add the Click event procedure of the cmdShowPropertyPage button to your form:

[VB.NET]
Private Sub cmdShowPropertyPage_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles cmdShowPropertyPage.Click     Codec.ShowPropertyPage() End Sub
[C#]
private void cmdShowPropertyPage_Click(object sender, System.EventArgs e) {     Codec.ShowPropertyPage(); }

Saving the Codec Properties

As described above, the codec properties are supplied as a binary data stream. A binary data stream is simply a list of bytes. It is recommended to save the byte count in the data stream as the first element in the file. Using this first element, when the data is loaded from file, a dynamic array can be sized or resized to the matching byte count in order to accommodate the data.

Add the Click event procedure of cmdSaveData to your form:

[VB.NET]
Private Sub cmdSaveData_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles cmdSaveData.Click     Try         Dim Filestream As New System.IO.FileStream("test.bin", System.IO.FileMode.Create, System.IO.FileAccess.Write)           ' Create the writer for data.         Dim BinWriter As New System.IO.BinaryWriter(Filestream)           BinWriter.Write(Codec.ToString())         BinWriter.Write(Codec.CompressorDataSize)         BinWriter.Write(Codec.CompressorData)           BinWriter.Close()         Filestream.Close()       Catch ex As System.Exception         MsgBox(ex.Message, MsgBoxStyle.Critical"Write error")     End Try End Sub
[C#]
private void cmdSaveData_Click(object sender, System.EventArgs e) {     try     {         System.IO.FileStream Filestream =  new System.IO.FileStream("test.bin"System.IO.FileMode.Create, System.IO.FileAccess.Write);         System.IO.BinaryWriter BinWriter = new System.IO.BinaryWriter(Filestream);         BinWriter.Write(Codec.Name);         BinWriter.Write(Codec.CompressorDataSize);         BinWriter.Write(Codec.CompressorData);           BinWriter.Close();         Filestream.Close();     }     catch( Exception Ex )     {         MessageBox.Show(Ex.Message);     } }

The codec properties will be saved in the file test.bin. Remember that the cmdSaveData button is only enabled, if AviCompressor.PropertyPageAvailable returns True. Alternatively, you can implement the following lines of code:

[VB.NET]
If Codec.PropertyPageAvailable Then     ' Do something like saving etc. Else     MsgBox "This codec does not support properties!" End If
[C#]
if( Codec.PropertyPageAvailable ) {     //  Do something like saving etc. } else {     MessageBox.Show( "This codec does not support properties!"); }

Loading the Codec Properties

Add the Click event procedure of cmdLoadData to your form:

[VB.NET]
Private Sub cmdLoadData_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles cmdLoadData.Click     Try         ' Create the reader for data.         Dim Filestrem As New System.IO.FileStream("test.bin", System.IO.FileMode.Open, System.IO.FileAccess.Read)         Dim BinReader As New System.IO.BinaryReader(Filestrem)           Dim CodecName As String           ' Retrieve the name of the codec from the codec configuration file.         CodecName = BinReader.ReadString()           ' Compare the codec name in the file with the current codec's name.         If Codec.Name = CodecName Then             Dim codecDataLen As Integer = BinReader.ReadInt32()             ' Assign the configuration data to the codec.             Codec.CompressorData = BinReader.ReadBytes(codecDataLen)         Else             MsgBox("The saved data does not match to the used codec." + Chr(13) + _                    "saved: " + CodecName + Chr(13) + _                    "used: " + Codec.Name)         End If         BinReader.Close()         Filestrem.Close()     Catch ex As System.Exception         MsgBox(ex.Message, MsgBoxStyle.Critical"Read error")     End Try End Sub
[C#]
private void cmdLoadData_Click(object sender, System.EventArgs e) {     try     {         System.IO.FileStream Filestream =  new System.IO.FileStream("test.bin"System.IO.FileMode.Open, System.IO.FileAccess.Read);         System.IO.BinaryReader BinReader = new System.IO.BinaryReader(Filestream);         String CodecName;           // Retrieve the name of the codec from the codec configuration file          CodecName = BinReader.ReadString();           //Compare the codec name in the file with the current codec's name.         if( Codec.Name == CodecName )         {             // Read the length of the binary data.             int codecDataLen = BinReader.ReadInt32();             // Assign the configuration data to the codec.             Codec.CompressorData = BinReader.ReadBytes(codecDataLen);         }         else         {             MessageBox.Show("The saved data does not match to the used codec.\n" +                     "saved: " + CodecName + "\n" +                      "used: " + Codec.Name);         }         BinReader.Close();         Filestream.Close();     }     catch( Exception Ex )     {         MessageBox.Show(Ex.Message);     }     }

As described above at the cmdSaveData button, the cmdLoadData button is only enabled if AviCompressor.PropertyPageAvailable returns True. Before assigning data to a codec, you should check whether it supports properties:

[VB.NET]
If Codec.PropertyPageAvailable Then     ' Do something like loading etc. Else     MsgBox "This codec does not support properties!" End If
[C#]
if( Codec.PropertyPageAvailable ) {     //  Do something like loading etc. } else {     MessageBox.Show( "This codec does not support properties!"); }

Using the Codec for Capture

For the sake of completeness, we have included the following statement that shows how to use the codec to capture an AVI file:

[VB.NET]
IcImagingControl1.AviStartCapture("test.avi", Codec)
[C#]
icImagingControl1.AviStartCapture("test.avi",Codec);

This is not included in the example.

<< Programmer's Guide

This site is part of The Imaging Source Network. Other sites include Company Portal, Image Processing, Astronomy Cameras, Astronomy Cameras Blog, Blog caméras d'astronomie, Astronomy Cameras Competition, TX Text Control, TX Text Control Blog and Forums.