Perform the following steps to create and run a multimedia capture DVR application using the LEADTOOLS Multimedia CaptureCtrl and PlayCtrl controls and DVR components of the LEADTOOLS MPEG-2 Transport module.
Start Visual Studio.
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 Application " in the Templates List.
Type the project name as "Multimedia DVR" in the Project Name field, and then click OK. If desired, type a new location for your project or select a directory using the Browse button, and then click OK.
In the "Solution Explorer" window, right-click the "References" folder, and select "Add Reference..." from the context menu. In the "Add Reference" dialog box, select the ".NET" tab and select Leadtools.Multimedia and click OK. Also, 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:
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.
Make sure Form1 is in design view. Go to the toolbox (View->Toolbox) and drag a CaptureCtrl control and a PlayCtrl control on the form. After adding it to the form, set the following properties on the controls:
Property | Value |
---|---|
Name | _capturectrl |
Anchor | Top, Bottom, Left |
Name | _playctrl |
Anchor | Top, Bottom, Right |
AutoStart | false |
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 |
Go to the toolbox (View->Toolbox) and drag two Button controls to the bottom of the form and set the following properties:
Property | Value |
---|---|
Name | _buttonCapture |
Text | Capture |
Anchor | Bottom, Right |
Name | _buttonPlay |
Text | Play |
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 LMMpgDmxTLib
Imports LMDVRSinkLib
Imports LMMPEG2EncoderLib
using Leadtools.Multimedia;
using LMMpgDmxTLib;
using LMDVRSinkLib;
using LMMPEG2EncoderLib;
Declare the following private variables:
Private Const SLIDER_MAX As Integer = 10000
Private _targetFile As String
Private _targetFolder As String
Private _capturing As Boolean
Private _mpegDemux As LMMpgDmxT
Private _dvrSink As ILMDVRSink
Private _firstPTS As Double
Private _lastPTS As Double
private const int SLIDER_MAX = 10000;
private string _targetFile;
private string _targetFolder;
private bool _capturing;
private LMMpgDmxT _mpegDemux;
private ILMDVRSink _dvrSink;
private double _firstPTS;
private double _lastPTS;
Add an event handler to the Form1 Load event and code it as follows:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If _capturectrl.VideoDevices.Count = 0 Then
Throw New Exception("No capture devices available")
End If
If _capturectrl.VideoDevices("Analog") Is Nothing Then
Throw New Exception("No Analog TV capture devices available")
End If
_capturectrl.VideoDevices("Analog").Selected = True
_capturectrl.UseVideoDeviceAudio = True
_capturing = False
_targetFolder = Path.Combine(Directory.GetCurrentDirectory(), "DVRFolder")
If (Not Directory.Exists(_targetFolder)) Then
Directory.CreateDirectory(_targetFolder)
End If
_targetFile = "capture.lbl"
_capturectrl.PreviewTap = CapturePreviewTap.Source
_capturectrl.Preview = True
_capturectrl.PreviewSource = CapturePreview.Video
End Sub
private void Form1_Load(object sender, System.EventArgs e)
{
if (_capturectrl.VideoDevices.Count == 0)
throw new Exception("No capture devices available");
if (_capturectrl.VideoDevices["Analog"] == null)
throw new Exception("No Analog TV capture devices available");
_capturectrl.VideoDevices["Analog"].Selected = true;
_capturectrl.UseVideoDeviceAudio = true;
_capturing = false;
_targetFolder = Path.Combine(Directory.GetCurrentDirectory(), "DVRFolder");
if (!Directory.Exists(_targetFolder))
Directory.CreateDirectory(_targetFolder);
_targetFile = "capture.lbl";
_capturectrl.PreviewTap = CapturePreviewTap.Source;
_capturectrl.Preview = true;
_capturectrl.PreviewSource = CapturePreview.Video;
}
Add the following helper methods as follows:
Private Function IsStreaming() As Boolean
Return (_capturectrl.VideoCaptureStreamType = Leadtools.Multimedia.Constants.MEDIATYPE_Stream)
End Function
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 bool IsStreaming()
{
return (_capturectrl.VideoCaptureStreamType == Constants.MEDIATYPE_Stream);
}
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 _capturectrl Progress event and code it as follows:
Private Sub _capturectrl_Progress(ByVal sender As Object, ByVal e As ProgressEventArgs) Handles _capturectrl.Progress
If Not _mpegDemux Is Nothing Then
_mpegDemux.RefreshPosition(0)
Dim curPTS As Double = _mpegDemux.CurrentStreamPTS
_firstPTS = _mpegDemux.FirstStreamPTS
_lastPTS = _mpegDemux.LastStreamPTS
If curPTS < _firstPTS AndAlso _playctrl.State = PlayState.Paused Then
_playctrl.Run()
End If
End If
End Sub
private void _capturectrl_Progress(object sender, ProgressEventArgs e)
{
if (_mpegDemux != null)
{
_mpegDemux.RefreshPosition(0);
double curPTS = _mpegDemux.CurrentStreamPTS;
_firstPTS = _mpegDemux.FirstStreamPTS;
_lastPTS = _mpegDemux.LastStreamPTS;
if (curPTS < _firstPTS && _playctrl.State == PlayState.Paused)
_playctrl.Run();
}
}
Add an event handler to the _playctrl TrackingPositionChanged event and code it as follows:
Private Sub _playctrl_TrackingPositionChanged(ByVal sender As System.Object, ByVal e As TrackingPositionChangedEventArgs) Handles _playctrl.TrackingPositionChanged
If Not _mpegDemux Is Nothing Then
_mpegDemux.RefreshPosition(0)
Dim curPTS As Double = _mpegDemux.CurrentStreamPTS
_firstPTS = _mpegDemux.FirstStreamPTS
_lastPTS = _mpegDemux.LastStreamPTS
_track.Value = PTSToSliderPosition(curPTS)
End If
End Sub
private void _playctrl_TrackingPositionChanged(object sender, TrackingPositionChangedEventArgs e)
{
if (_mpegDemux != null)
{
_mpegDemux.RefreshPosition(0);
double curPTS = _mpegDemux.CurrentStreamPTS;
_firstPTS = _mpegDemux.FirstStreamPTS;
_lastPTS = _mpegDemux.LastStreamPTS;
_track.Value = PTSToSliderPosition(curPTS);
}
}
Add an event handler to the _track Scroll event and code it as follows:
Private Sub _track_Scroll(ByVal sender As System.Object, ByVal e As EventArgs) Handles _track.Scroll
If Not _mpegDemux Is Nothing Then
Dim ptsPos As Double = SliderPositionToPTS(_track.Value)
_mpegDemux.CurrentStreamPTS = ptsPos
End If
End Sub
private void _track_Scroll(object sender, EventArgs e)
{
if (_mpegDemux != null)
{
double ptsPos = SliderPositionToPTS(_track.Value);
_mpegDemux.CurrentStreamPTS = ptsPos;
}
}
Add an event handler to the _capturectrl Complete event and code it as follows:
Private Sub _capturectrl_Complete(ByVal sender As System.Object, ByVal e As EventArgs) Handles _capturectrl.Complete
MessageBox.Show("Capture Complete")
_buttonCapture.Enabled = true
End Sub
private void _capturectrl_Complete(object sender, EventArgs e)
{
MessageBox.Show("Capture Complete");
_buttonCapture.Enabled = true;
}
Add an event handler to the _playctrl StateChanged event and code it as follows:
Private Sub _playctrl_StateChanged(ByVal sender As Object, ByVal e As StateChangedEventArgs) Handles _playctrl.StateChanged
If e.state = PlayState.Running Then
_mpegDemux = Nothing
_mpegDemux = TryCast(_playctrl.GetSubObject(PlayObject.Splitter), LMMpgDmxT)
End If
End Sub
private void _playctrl_StateChanged(object sender, StateChangedEventArgs e)
{
if (e.state == PlayState.Running)
{
_mpegDemux = null;
_mpegDemux = _playctrl.GetSubObject(PlayObject.Splitter) as LMMpgDmxT;
}
}
Add an event handler to the _buttonCapture Click event and code it as follows:
Private Sub _buttonCapture_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles _buttonCapture.Click
Try
If _capturing = True Then
_capturectrl.StopCapture()
Else
Dim recVideoComp As String = String.Empty
Dim recAudioComp As String = String.Empty
If IsStreaming() Then
_capturectrl.TargetFormats.DVR.Selected = True
_capturectrl.TargetFormat = TargetFormatType.DVR
_capturectrl.VideoCompressors.Selection = -1
_capturectrl.AudioCompressors.Selection = -1
Else
_capturectrl.TargetFormats.DVRTransport.Selected = True
recVideoComp = _capturectrl.TargetFormats.DVRTransport.RecommendedVideoCompressor
recAudioComp = _capturectrl.TargetFormats.DVRTransport.RecommendedAudioCompressor
_capturectrl.TargetFormat = TargetFormatType.DVRTransport
If recVideoComp <> String.Empty Then
_capturectrl.VideoCompressors(recVideoComp).Selected = True
End If
If recAudioComp <> String.Empty Then
_capturectrl.AudioCompressors(recAudioComp).Selected = True
End If
If _capturectrl.VideoCompressors.Mpeg2.Selected = True Then
Dim mpeg2Encoder As LMMPEG2Encoder = TryCast(_capturectrl.GetSubObject(CaptureObject.VideoCompressor), LMMPEG2Encoder)
If Not mpeg2Encoder Is Nothing Then
mpeg2Encoder.EncodingThreads = eMpeg2EncodingThreads.MPEG2_THREAD_AUTO
mpeg2Encoder.VideoFormat = eMPEG2VIDEOFORMAT.MPEG2_VF_NTSC
Marshal.ReleaseComObject(mpeg2Encoder)
End If
End If
End If
_capturectrl.Preview = True
_capturectrl.TargetFile = _targetFile
_capturectrl.ReadyCapture(CaptureMode.VideoAndAudio Or CaptureMode.InhibitRun)
_dvrSink = TryCast(_capturectrl.GetSubObject(CaptureObject.Sink), ILMDVRSink)
If Not _dvrSink Is Nothing Then
Dim dBuffSize As Double = 102400000 ' 100 MB
Dim lFileCount As Integer = 8 ' 8 buffer files
_dvrSink.StartChangingAttributes()
_dvrSink.FolderCount = 1
_dvrSink.FolderName(0) = _targetFolder
_dvrSink.SetBufferSize(0, lFileCount, dBuffSize)
_dvrSink.StopChangingAttributes(False)
Dim bufferFolder As String = _dvrSink.BaseName
End If
_capturectrl.RunCapture()
_buttonCapture.Enabled = False
_capturing = True
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
private void _buttonCapture_Click(object sender, System.EventArgs e)
{
try
{
if (_capturing == true)
_capturectrl.StopCapture();
else
{
string recVideoComp = string.Empty;
string recAudioComp = string.Empty;
if (IsStreaming())
{
_capturectrl.TargetFormats.DVR.Selected = true;
_capturectrl.TargetFormat = TargetFormatType.DVR;
_capturectrl.VideoCompressors.Selection = -1;
_capturectrl.AudioCompressors.Selection = -1;
}
else
{
_capturectrl.TargetFormats.DVRTransport.Selected = true;
recVideoComp = _capturectrl.TargetFormats.DVRTransport.RecommendedVideoCompressor;
recAudioComp = _capturectrl.TargetFormats.DVRTransport.RecommendedAudioCompressor;
_capturectrl.TargetFormat = TargetFormatType.DVRTransport;
if (recVideoComp != string.Empty)
_capturectrl.VideoCompressors[recVideoComp].Selected = true;
if (recAudioComp != string.Empty)
_capturectrl.AudioCompressors[recAudioComp].Selected = true;
if (_capturectrl.VideoCompressors.Mpeg2.Selected == true)
{
LMMPEG2Encoder mpeg2Encoder = _capturectrl.GetSubObject(CaptureObject.VideoCompressor) as LMMPEG2Encoder;
if (mpeg2Encoder != null)
{
mpeg2Encoder.EncodingThreads = eMpeg2EncodingThreads.MPEG2_THREAD_AUTO;
mpeg2Encoder.VideoFormat = eMPEG2VIDEOFORMAT.MPEG2_VF_NTSC;
Marshal.ReleaseComObject(mpeg2Encoder);
}
}
}
_capturectrl.Preview = true;
_capturectrl.TargetFile = _targetFile;
_capturectrl.ReadyCapture(CaptureMode.VideoAndAudio | CaptureMode.InhibitRun);
_dvrSink = _capturectrl.GetSubObject(CaptureObject.Sink) as ILMDVRSink;
if (_dvrSink != null)
{
double dBuffSize = 102400000; // 100 MB
int lFileCount = 8; // 8 buffer files
_dvrSink.StartChangingAttributes();
_dvrSink.FolderCount = 1;
_dvrSink.set_FolderName(0, _targetFolder);
_dvrSink.SetBufferSize(0, lFileCount, dBuffSize);
_dvrSink.StopChangingAttributes(false);
string bufferFolder = _dvrSink.BaseName;
}
_capturectrl.RunCapture();
_buttonCapture.Enabled = false;
_capturing = true;
}
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message);
}
}
Add an event handler to the _buttonPlay Click event and code it as follows:
Private Sub _buttonPlay_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles _buttonPlay.Click
Try
_mpegDemux = Nothing
_playCtrl.ResetSource()
_playCtrl.PreferredMPEG2Splitter = Leadtools.Multimedia.Constants.Filter_MPEG2_Transport_Demux
_playctrl.SourceFile = Path.Combine(_targetFolder, _targetFile)
_playctrl.Run
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
private void _buttonPlay_Click(object sender, System.EventArgs e)
{
try
{
_mpegDemux = null;
_playCtrl.ResetSource();
_playCtrl.PreferredMPEG2Splitter = Constants.Filter_MPEG2_Transport_Demux;
_playctrl.SourceFile = Path.Combine(_targetFolder, _targetFile);
_playctrl.Run();
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message);
}
}
Build, and Run the program to test it.