' Connect the pieces together, use the default renderer
Try
'AVI/MPEG
hr = icgb2.RenderStream(Nothing, Nothing, sourceFilter, baseGrabFlt, Nothing)
DsError.ThrowExceptionForHR(hr)
m_BitsPerPixel = 24
Catch ex As Exception
'WMV/ASF
hr = icgb2.RenderStream(Nothing, MediaType.Video, sourceFilter, baseGrabFlt, Nothing)
DsError.ThrowExceptionForHR(hr)
m_BitsPerPixel = 32
End Try
When the WMV exception is thrown I get an extra unconnected video renderer.
How do I kill this renderer?
Another problem:
When I play video with SetupGraph from DxPlay and mix it with text
using Graphics.FromImage(bitmapOverlay) and g.Drawstring,
g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
and
g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit
don't work. The text is far from smooth. The same goes for the video quality.
With SetupGraph from DxText both video and Text is smooth.
How can I get smooth graphics again?
Kind regards
Peter
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks, Snarfle.
Here is the VB code I ended up with.
Maybe it should be added to the samples.
I have added some comments.
Please correct them if they are wrong.
' Get the SampleGrabber interface
sampGrabber = TryCast(New SampleGrabber(), ISampleGrabber)
' Add the video source
hr = m_FilterGraph.AddSourceFilter(FileName, "Ds.NET FileFilter", capFilter)
DsError.ThrowExceptionForHR(hr)
'Find the video stream with IMediaDet
Dim md As DES.IMediaDet
' Number of video and audio streams
Dim Streams As Integer = Nothing
' The stream number we are looking for
Dim VidStream As Integer = Nothing
' The video pin
Dim iPinOutSource As IPin = Nothing
' The major type (vido)
Dim Type As System.Guid = Nothing
md = CType(New DES.MediaDet, IMediaDet)
md.put_Filename(FileName)
md.get_OutputStreams(Streams)
' Walk through the streams and find the video stream
For i As Integer = 0 To Streams - 1
' Put the stream number
md.put_CurrentStream(i)
' Get the major type
md.get_StreamType(Type)
If Type = MediaType.Video Then
' Found the video stream
VidStream = i
Exit For
End If
Next
' Find the video pin
iPinOutSource = DsFindPin.ByDirection(capFilter, PinDirection.Output, VidStream)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I finally found at least one way to make WMV files work.
Read the comment for an explanation.
Here is a VB solution:
' Hopefully this will be the video pin
Dim iPinOutSource As IPin = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0)
' Hope isn't good enough. AVI/MPEG files have ONE pin called "Output"
' The ASF/WMW video pin is called "Raw Video 1". Audio is called "Raw Audio 0"
' Get the name, and try again if the name points to ASF/WMV.
' If the name is "Raw Video 1", everything is fine. It's the right pin.
' If the name is "Raw Audio 0" pin 1 would probably be better.
Dim inf As PinInfo = Nothing
iPinOutSource.QueryPinInfo(inf)
If inf.name = "Raw Audio 0" Then
iPinOutSource = DsFindPin.ByDirection(capFilter, PinDirection.Output, 1)
End If
I think I found a better way.
I have tried it with wmv, avi and mpg files.
Dim md As DES.IMediaDet
Dim st As String = Nothing
Dim streams As Integer = Nothing
Dim VidStream As Integer = Nothing
Dim iPinOutSource As IPin = Nothing
Const VideoGUID As String = "{73646976-0000-0010-8000-00AA00389B71}"
I get this error in SetupGraph:
"No combination of intermediate filters could be found to make the connection".
It happens here:
hr = m_FilterGraph.Connect(iPinOut, iPinIn)
DsError.ThrowExceptionForHR(hr)
It has been discussed before but no solution was mentioned.
When I use SetupGraph from DxPlay, I can play both ASF and AVI
if I modify this line:
hr = icgb2.RenderStream(Nothing, Nothing, sourceFilter, baseGrabFlt, Nothing)
like this:
' Connect the pieces together, use the default renderer
Try
'AVI/MPEG
hr = icgb2.RenderStream(Nothing, Nothing, sourceFilter, baseGrabFlt, Nothing)
DsError.ThrowExceptionForHR(hr)
m_BitsPerPixel = 24
Catch ex As Exception
'WMV/ASF
hr = icgb2.RenderStream(Nothing, MediaType.Video, sourceFilter, baseGrabFlt, Nothing)
DsError.ThrowExceptionForHR(hr)
m_BitsPerPixel = 32
End Try
When the WMV exception is thrown I get an extra unconnected video renderer.
How do I kill this renderer?
Another problem:
When I play video with SetupGraph from DxPlay and mix it with text
using Graphics.FromImage(bitmapOverlay) and g.Drawstring,
g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
and
g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit
don't work. The text is far from smooth. The same goes for the video quality.
With SetupGraph from DxText both video and Text is smooth.
How can I get smooth graphics again?
Kind regards
Peter
Thanks, Snarfle.
Here is the VB code I ended up with.
Maybe it should be added to the samples.
I have added some comments.
Please correct them if they are wrong.
' Get the SampleGrabber interface
sampGrabber = TryCast(New SampleGrabber(), ISampleGrabber)
' Add the video source
hr = m_FilterGraph.AddSourceFilter(FileName, "Ds.NET FileFilter", capFilter)
DsError.ThrowExceptionForHR(hr)
'Find the video stream with IMediaDet
Dim md As DES.IMediaDet
' Number of video and audio streams
Dim Streams As Integer = Nothing
' The stream number we are looking for
Dim VidStream As Integer = Nothing
' The video pin
Dim iPinOutSource As IPin = Nothing
' The major type (vido)
Dim Type As System.Guid = Nothing
md = CType(New DES.MediaDet, IMediaDet)
md.put_Filename(FileName)
md.get_OutputStreams(Streams)
' Walk through the streams and find the video stream
For i As Integer = 0 To Streams - 1
' Put the stream number
md.put_CurrentStream(i)
' Get the major type
md.get_StreamType(Type)
If Type = MediaType.Video Then
' Found the video stream
VidStream = i
Exit For
End If
Next
' Find the video pin
iPinOutSource = DsFindPin.ByDirection(capFilter, PinDirection.Output, VidStream)
While I'm glad this is working for you, I still think a better general-purpose solution would be to examine the media type of the pins of capFilter.
I finally found at least one way to make WMV files work.
Read the comment for an explanation.
Here is a VB solution:
' Hopefully this will be the video pin
Dim iPinOutSource As IPin = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0)
' Hope isn't good enough. AVI/MPEG files have ONE pin called "Output"
' The ASF/WMW video pin is called "Raw Video 1". Audio is called "Raw Audio 0"
' Get the name, and try again if the name points to ASF/WMV.
' If the name is "Raw Video 1", everything is fine. It's the right pin.
' If the name is "Raw Audio 0" pin 1 would probably be better.
Dim inf As PinInfo = Nothing
iPinOutSource.QueryPinInfo(inf)
If inf.name = "Raw Audio 0" Then
iPinOutSource = DsFindPin.ByDirection(capFilter, PinDirection.Output, 1)
End If
The same thing in C#:
IPin iPinOutSource = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0);
PinInfo inf = null;
iPinOutSource.QueryPinInfo(out inf);
if (inf.name == "Raw Audio 0")
{
iPinOutSource = DsFindPin.ByDirection(capFilter, PinDirection.Output, 1);
}
This seems to work. I have tried several AVI, MPEG and WMV files.
But is this solution foolproof?
Is there a better or more elegant way to do this?
Peter
How about getting the media type? The majorType should tell you what you are dealing with.
I think I found a better way.
I have tried it with wmv, avi and mpg files.
Dim md As DES.IMediaDet
Dim st As String = Nothing
Dim streams As Integer = Nothing
Dim VidStream As Integer = Nothing
Dim iPinOutSource As IPin = Nothing
Const VideoGUID As String = "{73646976-0000-0010-8000-00AA00389B71}"
md = CType(New DES.MediaDet, IMediaDet)
md.put_Filename(FileName)
md.get_OutputStreams(streams)
For i As Integer = 0 To streams - 1
md.put_CurrentStream(i)
md.get_StreamTypeB(st)
If st = VideoGUID Then
VidStream = i
Exit For
End If
Next
iPinOutSource = DsFindPin.ByDirection(capFilter, PinDirection.Output, VidStream)
Peter
And the same code in C#:
DirectShowLib.DES.IMediaDet md = null;
string st = null;
int streams = 0;
int VidStream = 0;
IPin iPinOutSource = null;
const string VideoGUID = "{73646976-0000-0010-8000-00AA00389B71}";
md = (IMediaDet)(new DirectShowLib.DES.MediaDet());
md.put_Filename(FileName);
md.get_OutputStreams(out streams);
for (int i = 0; i < streams; i++)
{
md.put_CurrentStream(i);
md.get_StreamTypeB(out st);
if (st == VideoGUID)
{
VidStream = i;
break;
}
}
iPinOutSource = DsFindPin.ByDirection(capFilter, PinDirection.Output, VidStream);
Peter
What you call VideoGUID, we call MediaType.Video. It's in uuids.cs.
You would probably do better comparing it with get_StreamType() rather than converting it back to a string.