Menu

DxText and DxScan can't handle ASF/WMV files

Peter_B
2008-10-20
2012-10-29
  • Peter_B

    Peter_B - 2008-10-20

    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

     
    • Peter_B

      Peter_B - 2008-10-29

      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)

       
      • snarfle

        snarfle - 2008-10-29

        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.

         
    • Peter_B

      Peter_B - 2008-10-25

      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

       
      • snarfle

        snarfle - 2008-10-25

        How about getting the media type? The majorType should tell you what you are dealing with.

         
    • Peter_B

      Peter_B - 2008-10-28

      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

       
    • Peter_B

      Peter_B - 2008-10-28

      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

       
      • snarfle

        snarfle - 2008-10-28

        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.

         

Log in to post a comment.