Perform the following steps to create and run a multimedia player DVR application using the LEADTOOLS Multimedia ConvertCtrl and PlayCtrl controls and the DVR components of the LEADTOOLS MPEG-2 Transport Module.
-
Start Visual Studio .NET.
-
Choose File->New->Project... from the menu.
-
In the New Project dialog box, choose either "Visual C# Projects" or "VB Projects" in the Projects Type List, and choose "Windows Forms Application " in the Templates List.
-
Type the project name as "Multimedia Player DVR" in the Project Name field, and then choose OK. If desired, type a new location for your project or select a directory using the Browse button, and then click OK.
-
To add a reference to the Leadtools.Multimedia.dll right-click the "References" folder in the Solution Explorer window. Select "Add Reference..." from the context menu. In the "Add Reference" dialog box, select the ".NET" tab and select Leadtools.Multimedia.dll and click OK.
-
Next, add the reference to the LEADTOOLS COM Objects. Right-click the "References" folder, and select "Add Reference..." from the context menu. In the "Add Reference" dialog box, select the "COM" tab and select the following:
- LEAD MPEG-2 Transport Multiplexer Library
- LEAD MPEG2 Transport Demultiplexer Library
- LEAD DVR Sink Library
Note: The above COM objects must be registered; in case they were not; using regsvr32. For more information, refer to DirectShow Registry-free Activation. Next click OK to add the references.
-
Make sure Form1 is in design view. Go to the toolbox (View->Toolbox) and drag a ConvertCtrl control and a PlayCtrl control on the form. NOTE: If you do not have ConvertCtrl or PlayCtrl controls in your toolbox, select Tools->Choose Toolbox Items from the menu. Click Browse and then select Leadtools.Multimedia.dll from "<LEADTOOLS_INSTALLDIR>\Bin\Dotnet\Win32" and then click Open and then click OK. After adding these controls to the form, set the following properties:
Property |
Value |
Name |
_convertctrl |
Anchor |
Top, Left |
BackColor |
Black |
Name |
_playctrl |
Anchor |
Top, Bottom, Left, Right |
AutoStart |
False |
-
Go to the toolbox (View->Toolbox) and drag a Text control on the form (below the convert control) and set the following properties:
Property |
Value |
Name |
_txtSrcFile |
Anchor |
Bottom, Left |
Locked |
True |
-
Go to the toolbox (View->Toolbox) and drag a Button control to the right of the text control and set the following properties:
Property |
Value |
Name |
_buttonBrowse |
Text |
... |
Anchor |
Bottom, Left |
-
Go to the toolbox (View->Toolbox) and drag a TrackBar control on the form (below the play control) and set the following properties:
Property |
Value |
Name |
_track |
Anchor |
Bottom, Left, Right |
Maximum |
10000 |
-
Go to the toolbox (View->Toolbox) and drag six Button controls to the bottom of the form (first one below the convert control and the others below the play control) and set the following properties:
Property |
Value |
Name |
_buttonStartStop |
Text |
Start |
Anchor |
Bottom, Left |
Property |
Value |
Name |
_buttonStop |
Text |
Stop |
Anchor |
Bottom, Right |
Property |
Value |
Name |
_buttonPlayMPEG2StreamWithDVRBuffer |
Text |
Play MPEG2 Stream With DVR Buffer |
Anchor |
Bottom, Right |
Property |
Value |
Name |
_buttonPlayDVRBufferFile |
Text |
Play DVR Buffer File |
Anchor |
Bottom, Right |
Property |
Value |
Name |
_buttonSetDVRBufferLocations |
Text |
Set DVR Buffer Locations |
Anchor |
Bottom, Right |
Property |
Value |
Name |
_buttonCopyBufferedDVRData |
Text |
Copy Buffered DVR Data |
Anchor |
Bottom, Right |
-
Switch Form1 to code view (right-click Form1 in the Solution Explorer then choose View Code) and add the following lines to the beginning of the file:
Imports Leadtools.Multimedia
Imports System.Runtime.InteropServices
Imports LMMpg2MxTLib
Imports LMMpgDmxTLib
Imports LMDVRSinkLib
using Leadtools.Multimedia;
using System.Runtime.InteropServices;
using LMMpg2MxTLib;
using LMMpgDmxTLib;
using LMDVRSinkLib;
-
Declare the following private variable:
Private Const SLIDER_MAX As Integer = 10000
Private _streaming As Boolean = False
Private _firstPTS As Double
Private _lastPTS As Double
Private const int SLIDER_MAX = 10000;
Private bool _streaming = false;
Private double _firstPTS;
Private double _lastPTS;
-
Add an event handler to the _convertctrl Started event and add the following code:
Private Sub _convertCtrl_Started(ByVal sender As Object, ByVal e As EventArgs) Handles _convertCtrl.Started
_streaming = True
_buttonBrowse.Enabled = False
_buttonPlayMPEG2StreamWithDVRBuffer.Enabled = True
_buttonSetDVRBufferLocations.Enabled = True
_buttonCopyBufferedDVRData.Enabled = True
End Sub
void _convertCtrl_Started(object sender, EventArgs e)
{
_streaming = true;
_buttonBrowse.Enabled = false;
_buttonPlayMPEG2StreamWithDVRBuffer.Enabled = True;
_buttonSetDVRBufferLocations.Enabled = True;
_buttonCopyBufferedDVRData.Enabled = True;
}
-
Add an event handler to the _convertctrl Complete event and add the following code:
Private Sub _convertCtrl_Complete(ByVal sender As Object, ByVal e As EventArgs) Handles _convertCtrl.Complete
If _streaming = True Then
_convertCtrl.StartConvert()
Else
_buttonStartStop.Text = "Start"
_buttonBrowse.Enabled = True
_buttonPlayMPEG2StreamWithDVRBuffer.Enabled = False
_buttonSetDVRBufferLocations.Enabled = False
_buttonCopyBufferedDVRData.Enabled = False
End If
End Sub
void _convertCtrl_Complete(object sender, EventArgs e)
{
if (_streaming == true)
_convertCtrl.StartConvert();
else
{
_buttonStartStop.Text = "Start";
_buttonBrowse.Enabled = true;
_buttonPlayMPEG2StreamWithDVRBuffer.Enabled = False;
_buttonSetDVRBufferLocations.Enabled = False;
_buttonCopyBufferedDVRData.Enabled = False;
}
}
-
Add an event handler to the _playctrl TrackingPositionChanged event and add the following code:
Private Sub _playctrl_TrackingPositionChanged(ByVal sender As Object, ByVal e As TrackingPositionChangedEventArgs) Handles _playctrl.TrackingPositionChanged
Dim demux As LMMpgDmxT = TryCast(_playctrl.GetSubObject(PlayObject.Splitter), LMMpgDmxT)
If Not demux Is Nothing Then
demux.RefreshPosition(0)
_firstPTS = demux.FirstStreamPTS
_lastPTS = demux.LastStreamPTS
_track.Value = PTSToSliderPosition(demux.CurrentStreamPTS)
Marshal.ReleaseComObject(demux)
End If
End Sub
void _playctrl_TrackingPositionChanged(object sender, TrackingPositionChangedEventArgs e)
{
LMMpgDmxT demux = _playctrl.GetSubObject(PlayObject.Splitter) as LMMpgDmxT;
if (demux != null)
{
demux.RefreshPosition(0);
_firstPTS = demux.FirstStreamPTS;
_lastPTS = demux.LastStreamPTS;
_track.Value = PTSToSliderPosition(demux.CurrentStreamPTS);
Marshal.ReleaseComObject(demux);
}
}
-
Add an event handler to the _track Scroll event and add the following code:
Private Sub _track_Scroll(ByVal sender As Object, ByVal e As EventArgs) Handles _track.Scroll
Dim demux As LMMpgDmxT = TryCast(_playctrl.GetSubObject(PlayObject.Splitter), LMMpgDmxT)
If Not demux Is Nothing Then
demux.RefreshPosition(0)
demux.CurrentStreamPTS = SliderPositionToPTS(_track.Value)
Marshal.ReleaseComObject(demux)
End If
End Sub
private void _track_Scroll(object sender, EventArgs e)
{
LMMpgDmxT demux = _playctrl.GetSubObject(PlayObject.Splitter) as LMMpgDmxT;
if (demux != null)
{
demux.RefreshPosition(0);
demux.CurrentStreamPTS = SliderPositionToPTS(_track.Value);
Marshal.ReleaseComObject(demux);
}
}
-
Add the following helper methods for use by the _track control's scroll and _playctrl track positioning handlers:
Private Function PTSToSliderPosition(ByVal curPTS As Double) As Integer
Dim retVal As Integer = 0
If curPTS <= _firstPTS Then
retVal = 0
ElseIf curPTS >= _lastPTS Then
retVal = SLIDER_MAX
Else
retVal = CInt(((curPTS - _firstPTS) * SLIDER_MAX) / (_lastPTS - _firstPTS) + 0.5)
End If
Return retVal
End Function
Private Function SliderPositionToPTS(ByVal nPos As Integer) As Double
Return _firstPTS + CDbl(nPos) * (_lastPTS - _firstPTS) / CDbl(SLIDER_MAX)
End Function
private int PTSToSliderPosition(double curPTS)
{
int retVal = 0;
if (curPTS <= _firstPTS)
retVal = 0;
else if (curPTS >= _lastPTS)
retVal = SLIDER_MAX;
else
retVal = (int)(((curPTS - _firstPTS) * SLIDER_MAX) / (_lastPTS - _firstPTS) + 0.5);
return retVal;
}
private double SliderPositionToPTS(int nPos)
{
return _firstPTS + (double)nPos * (_lastPTS - _firstPTS) / (double)SLIDER_MAX;
}
-
Add an event handler to the _buttonBrowse Click event and add the following code:
Private Sub _btnBrowse_Click(ByVal sender As Object, ByVal e As EventArgs) Handles _buttonBrowse.Click
Dim ofn As OpenFileDialog = New OpenFileDialog()
ofn.FileName = _txtSrcFile.Text
ofn.FilterIndex = 0
If _txtSrcFile.Text <> String.Empty Then
ofn.InitialDirectory = Path.GetDirectoryName(_txtSrcFile.Text)
Else
ofn.InitialDirectory = Directory.GetCurrentDirectory()
End If
ofn.Multiselect = False
ofn.Title = "Select Source Video"
ofn.CheckFileExists = True
ofn.Filter = "MPEG2 Video Files (*.mpg)|*.mpg | All files (*.*)|*.*"
If ofn.ShowDialog() = DialogResult.OK Then
_txtSrcFile.Text = ofn.FileName
End If
End Sub
private void _btnBrowse_Click(object sender, EventArgs e)
{
OpenFileDialog ofn = new OpenFileDialog();
ofn.FileName = _txtSrcFile.Text;
ofn.FilterIndex = 0;
if (_txtSrcFile.Text != string.Empty)
ofn.InitialDirectory = Path.GetDirectoryName(_txtSrcFile.Text);
else
ofn.InitialDirectory = Directory.GetCurrentDirectory();
ofn.Multiselect = false;
ofn.Title = "Select Source Video";
ofn.CheckFileExists = true;
ofn.Filter = "MPEG2 Video Files (*.mpg)|*.mpg | All files (*.*)|*.*";
if (ofn.ShowDialog() == DialogResult.OK)
{
_txtSrcFile.Text = ofn.FileName;
}
}
-
Add an event handler to the _buttonStartStop Click event and add the following code:
Private Sub _btnStartStop_Click(ByVal sender As Object, ByVal e As EventArgs) Handles _buttonStartStop.Click
Dim srcFile As String = _txtSrcFile.Text
If _streaming = False Then
If srcFile <> String.Empty AndAlso File.Exists(srcFile) Then
_convertCtrl.SourceFile = srcFile
_convertCtrl.AllowedStreams = StreamFormatType.AudioVideoCC
_convertCtrl.PreferredMPEG2Splitter = Leadtools.Multimedia.Constants.Filter_MPEG2_Transport_Demux
_convertCtrl.TargetFormat = TargetFormatType.MPEG2Transport
_convertCtrl.Preview = True
_convertCtrl.TargetFile = "udp://127.0.0.1:9005"
Dim mux As LMMpg2MxT = TryCast(_convertCtrl.GetSubObject(ConvertObject.TargetFilter), LMMpg2MxT)
If Not mux Is Nothing Then
mux.OutputType = CInt(LMMpg2MxTLib.Mpg2MxT_OutputType.Mpg2MxT_OutputType_Broadcast)
mux.ResyncInterval = 10
Marshal.ReleaseComObject(mux)
End If
Try
_convertCtrl.StartConvert()
_buttonStartStop.Text = "Stop"
_buttonBrowse.Enabled = False
Catch e1 As Exception
End Try
End If
Else
If _streaming = True Then
_convertCtrl.StopConvert()
_buttonStartStop.Text = "Start"
_buttonBrowse.Enabled = True
End If
End If
End Sub
private void _btnStartStop_Click(object sender, EventArgs e)
{
string srcFile = _txtSrcFile.Text;
if (_streaming == false)
{
if (srcFile != string.Empty && File.Exists(srcFile))
{
_convertCtrl.SourceFile = srcFile;
_convertCtrl.AllowedStreams = StreamFormatType.AudioVideoCC;
_convertCtrl.PreferredMPEG2Splitter = Constants.Filter_MPEG2_Transport_Demux;
_convertCtrl.TargetFormat = TargetFormatType.MPEG2Transport;
_convertCtrl.Preview = true;
_convertCtrl.TargetFile = @"udp://127.0.0.1:9005";
LMMpg2MxT mux = _convertCtrl.GetSubObject(ConvertObject.TargetFilter) as LMMpg2MxT;
if (mux != null)
{
mux.OutputType = (int)LMMpg2MxTLib.Mpg2MxT_OutputType.Mpg2MxT_OutputType_Broadcast;
mux.ResyncInterval = 10;
Marshal.ReleaseComObject(mux);
}
try
{
_convertCtrl.StartConvert();
_buttonStartStop.Text = "Stop";
_buttonBrowse.Enabled = false;
}
catch (Exception) { }
}
}
else
{
if (_streaming == true)
{
_convertCtrl.StopConvert();
_buttonStartStop.Text = "Start";
_buttonBrowse.Enabled = true;
}
}
}
-
Add an event handler to the _buttonStop Click event and code it as follows:
Private Sub _buttonStop_Click(ByVal sender As Object, ByVal e As EventArgs) Handles _buttonStop.Click
If _playctrl.State = PlayState.Running Then
_playctrl.Stop()
End If
End Sub
private void _buttonStop_Click(object sender, EventArgs e)
{
if (_playctrl.State == PlayState.Running)
{
_playctrl.Stop();
}
}
-
Add an event handler to the _buttonPlayMPEG2StreamWithDVRBuffer Click event to play a UDP MPEG2 Stream with DVR Buffering and add the following code:
Private Sub _buttonPlayMPEG2StreamWithDVRBuffer_Click(ByVal sender As Object, ByVal e As EventArgs) Handles _buttonPlayMPEG2StreamWithDVRBuffer.Click
Try
' Open the UDP Stream, but don't auto start
_playctrl.AutoStart = False
_playctrl.SourceFile = "udp://127.0.0.1:9005"
Dim DVRSink As LMDVRSinkLib.LMDVRSink
DVRSink = DirectCast(_playctrl.GetSubObject(PlayObject.SourceFilter), LMDVRSinkLib.LMDVRSink)
' Tell the DVR Sink that settings are about to change
DVRSink.StartChangingAttributes()
' Set only one DVR buffer folder
DVRSink.FolderCount = 1
' Set the buffer base file name to 'Capture.LBL'
DVRSink.BaseName = "Capture.LBL"
' Set the buffer folder location to 'C:\Temp\DVR'
DVRSink.FolderName(0) = ("C:\Temp\DVR")
' Set the buffer folder to have 5 buffer data files, each at 100MB max size
DVRSink.SetBufferSize(0, 5, 102400000)
' Commit the changed settings now
DVRSink.StopChangingAttributes(False)
' Run the stream
_playctrl.Run()
Catch ex As Exception
MessageBox.Show(Me, ex.Message)
End Try
End Sub
private void _buttonPlayMPEG2StreamWithDVRBuffer_Click(object sender, EventArgs e)
{
try
{
// Open the UDP Stream, but don't auto start
_playctrl.AutoStart = false;
_playctrl.SourceFile = "udp://127.0.0.1:9005";
LMDVRSinkLib.LMDVRSink DVRSink;
DVRSink = (LMDVRSinkLib.LMDVRSink)(_playctrl.GetSubObject(PlayObject.SourceFilter));
// Tell the DVR Sink that settings are about to change
DVRSink.StartChangingAttributes();
// Set only one DVR buffer folder
DVRSink.FolderCount = 1;
// Set the buffer base file name to 'Capture.LBL'
DVRSink.BaseName = "Capture.LBL";
// Set the buffer folder location to 'C:\Temp\DVR'
DVRSink.set_FolderName(0, "C:\\Temp\\DVR");
// Set the buffer folder to have 5 buffer data files, each at 100MB max size
DVRSink.SetBufferSize(0, 5, 102400000);
// Commit the changed settings now
DVRSink.StopChangingAttributes(false);
// Run the stream
_playctrl.Run();
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message);
}
}
-
Add an event handler to the _buttonPlayDVRBufferFile Click event to play a DVR buffer file and add the following code:
Private Sub _buttonPlayDVRBufferFile_Click(ByVal sender As Object, ByVal e As EventArgs) Handles _buttonPlayDVRBufferFile.Click
Try
' Set the source file on the player
_playctrl.SourceFile = "C:\Temp\DVR\Capture.LBL"
' Run the player
_playctrl.Run()
Catch ex As Exception
MessageBox.Show(Me, ex.Message)
End Try
End Sub
private void _buttonPlayDVRBufferFile_Click(object sender, EventArgs e)
{
try
{
// Set the source file on the player
_playctrl.SourceFile = "C:\\Temp\\DVR\\Capture.LBL";
// Run the stream
_playctrl.Run();
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message);
}
}
-
Add an event handler to the _buttonSetDVRBufferLocations Click event to Set DVR Buffer Locations on More Than One Physical Disk and code it as follows:
Private Sub _buttonSetDVRBufferLocations_Click(ByVal sender As Object, ByVal e As EventArgs) Handles _buttonSetDVRBufferLocations.Click
Try
' Open the UDP Stream, but don't auto start
_playctrl.AutoStart = false
_playctrl.SourceFile = "udp://127.0.0.1:9005"
Dim DVRSink As LMDVRSinkLib.LMDVRSink
DVRSink = DirectCast(_playctrl.GetSubObject(PlayObject.SourceFilter), LMDVRSinkLib.LMDVRSink)
' Tell sink we are starting to change settings
DVRSink.StartChangingAttributes()
' Set Two buffer locations
DVRSink.FolderCount = 2
' Set base file name
DVRSink.BaseName = "Capture.LBL"
' Set buffer folder 1 location
DVRSink.FolderName(0) = "C:\Temp\DVR"
' Set buffer folder 1 to have 2 buffer data files, each at 16MB max file size
DVRSink.SetBufferSize(0, 2, 16 * 1024000)
' Set buffer folder 2 location
DVRSink.FolderName(1) = "D:\Temp\DVR"
' Set buffer folder 2 to have 4 buffer data files, each at 8MB max file size
DVRSink.SetBufferSize(1, 4, 8192000)
' Tell sink to apply the changes
DVRSink.StopChangingAttributes(False)
' Run the player
_playctrl.Run()
Catch ex As Exception
MessageBox.Show(Me, ex.Message)
End Try
End Sub
private void _buttonSetDVRBufferLocations_Click(object sender, EventArgs e)
{
try
{
// Open the UDP Stream, but don't auto start
_playctrl.AutoStart = false;
_playctrl.SourceFile = "udp://127.0.0.1:9005";
LMDVRSinkLib.LMDVRSink DVRSink;
DVRSink = (LMDVRSinkLib.LMDVRSink)(_playctrl.GetSubObject(PlayObject.SourceFilter));
// Tell sink we are starting to change settings
DVRSink.StartChangingAttributes();
// Set Two buffer locations
DVRSink.FolderCount = 2;
// Set base file name
DVRSink.BaseName = "Capture.LBL";
// Set buffer folder 1 location
DVRSink.set_FolderName(0, "C:\\Temp\\DVR");
// Set buffer folder 1 to have 2 buffer data files, each at 16MB max file size
DVRSink.SetBufferSize(0, 2, 16 * 1024000);
// Set buffer folder 2 location
DVRSink.set_FolderName(1, "D:\\Temp\\DVR");
// Set buffer folder 2 to have 4 buffer data files, each at 8MB max file size
DVRSink.SetBufferSize(1, 4, 8192000);
// Tell sink to apply the changes
DVRSink.StopChangingAttributes(false);
// Run the player
_playctrl.Run();
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message);
}
}
-
Add an event handler to the _buttonCopyBufferedDVRData Click event to play a DVR buffer file and add the following code:
Private Sub _buttonCopyBufferedDVRData_Click(ByVal sender As Object, ByVal e As EventArgs) Handles _buttonCopyBufferedDVRData.Click
Try
Dim first As Double
Dim last As Double
Dim total As Double
_playctrl.AutoStart = False
_playctrl.SourceFile = "udp://127.0.0.1:9005"
Dim DVRSink As LMDVRSinkLib.LMDVRSink
DVRSink = DirectCast(_playctrl.GetSubObject(PlayObject.SourceFilter), LMDVRSinkLib.LMDVRSink)
' Get available range to copy
DVRSink.GetAvailabilityInfo(first, last, total)
' Copy the data to the new file
DVRSink.CopyBufferToFile("C:\Temp\DVR\Copied_Capture.mpg", first, last)
Catch ex As Exception
MessageBox.Show(Me, ex.Message)
End Try
End Sub
private void _buttonCopyBufferedDVRData_Click(object sender, EventArgs e)
{
try
{
double first;
double last;
double total;
// Open the UDP Stream, but don't auto start
_playctrl.AutoStart = false;
_playctrl.SourceFile = "udp://127.0.0.1:9005";
LMDVRSinkLib.LMDVRSink DVRSink;
DVRSink = (LMDVRSinkLib.LMDVRSink)(_playctrl.GetSubObject(PlayObject.SourceFilter));
// Get available range to copy
DVRSink.GetAvailabilityInfo(out first, out last, out total);
// Copy the data to the new file
DVRSink.CopyBufferToFile("C:\\Temp\\DVR\\Copied_Capture.mpg", first, last);
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message);
}
}
-
Build, and Run the program to test it. Click the [...] browse button to locate a video file for the convert / streaming output. Then click the Start button to begin streaming. Click the Play MPEG2 Stream With DVR Buffer button to test playing a UDP MPEG2 Stream with DVR Buffering. Click the Play DVR Buffer button to test playing a DVR buffer file. Click the Set DVR Buffer Locations button to test Setting DVR Buffer Locations on More Than One Physical Disk and play a UDP MPEG2 Stream with DVR Buffering. Click the Copy Buffered DVR Data button to test copy buffered DVR data to a new file. Finally, drag the track bar control to reposition the stream playback.