Menu

Write Script Stream to WMV in DirectShow.NET

Mark R
2009-09-01
2012-10-29
  • Mark R

    Mark R - 2009-09-01

    I want to inject text into a script stream input pin of an ASF Writer filter while the graph is running. I have successfully created a .prx profile and loaded it into the Writer so the writer has a video stream, an audio stream, and a script stream. The video and audio source is a logitech orbit USB camera.

    While the graph is running, I want to insert text samples into the ASF Writer's script stream pin at presentation time so the text can be displayed at the correct time during playback. I think the problem is the source filter...I don't have one!!!

    I have tried to use the GSSF as the source and configuring the mediatype, but still no success. Could anyone point me in the right direction as to how to do this in C#?

    Thanks,

    Mark

     
    • Mark R

      Mark R - 2009-09-02

      I'll run the project again later today and find out exactly what a "short time" is.

      I am using the same method as the GSSF sample for the SetTime property. I am not setting the MediaTime property, however.

      Yes, I set every frame's SetSyncPoint to true. Yes, I am sending some text for every frame so I have not set SetDiscontinuity.

      I have not found any samples that have scripts or text embedded, so I haven't been able to see what's different. If you have any ideas where a WMV may be that includes this data, that would be good.

      Thanks for your responses...I'll post again once I know what exactly a "short time" is!

      Mark

       
    • snarfle

      snarfle - 2009-09-01

      I haven't done much with script, so I don't know how much help I can be.

      However, my first thought would also have been GSSF. What problems did you encounter here?

       
    • Mark R

      Mark R - 2009-09-01

      First, I had to do some work to get the output pin on the GSSF to be able to connect to the Script Stream input pin on the ASF Writer. Based upon the .PRX profile I created, the MajorType for a Script Stream is a GUID: {73636D64-0000-0010-8000-00AA00389B71}.

      I am having to mix both the DirectShow and WindowsMedia docs to find all that I need. According to the WM docs under the heading of "Configuring Script Streams", this statement is made:

      "Script streams need to have the formattype member of WM_MEDIA_TYPE set to WMFORMAT_Script, which indicates that the pbFormat member points to a WMSCRIPTFORMAT structure"....and...WMSCRIPTFORMAT.scriptType = "GUID identifying the type of script commands in a script stream. Always set to WMSCRIPTTYPE_TwoStrings."

      The WMFORMAT_Script and WMSCRIPTTYPE_TwoStrings are Guids and the WMSCRIPTFORMAT structure is defined in C++ as:

      typedef struct tagWMSCRIPTFORMAT{
      GUID scriptType;
      } WMSCRIPTFORMAT;

      These are identified in the wmsdkidl.h header file. So, in C#, I created the equivalent:

      [StructLayout(LayoutKind.Sequential)]
      public class WMSCRIPTFORMAT
      {
      public Guid scriptType;
      }

      and also...

      private Guid WMFORMAT_Script = new Guid("{5C8510F2-DEBE-4CA7-BBA5-F07A104F8DFF}");

      private Guid WMSCRIPTTYPE_TwoStrings = new Guid("{82F38A70-C29F-11D1-97AD-00A0C95EA850}")

      With this, I obtain the AMMediaType object from the input pin of the ASF Writer's for the Script Stream. I will use this AMMediaType object for the necessary call to the GSSF's SetMediaTypeEx method. However, before the call, I modify the properties of the AMMediaType object, since only the MajorType property is set. The formatType and formatPtr are not set. I set the formatType to the WMFORMAT_Script Guid. I create a WMSCRIPTFORMAT object and set the scriptType to the WMSCRIPTTYPE_TwoStrings Guid. I create an IntPtr for the formatPtr property by using Marshal.SizeOf, Marshal.AllocCoTaskMem and Marshal.StructureToPtr.

      Once I have this AMMediaType object set with these properties, I call the GSSF's SetMediaTypeEx method and pass it the AMMediaType object with a butter set to 1024. HRESULT returns 0. I set the SetBitmapCB to an object of a class, where within that class is the SampleCallback method which will be notified for each frame. I connect the GSSF to the ASF Writer. HRESULT returns 0.

      I run the graph and all seems well. The SampleCallback function is called for every frame as I initially just send a Debug.Writeline to see. The buffer for the IMediaSample pSample parameter is just as expected at 1024 bytes. I replace the buffer with a text string in accordance with what a script is supposed to look like with something like this:

              string myScript = "TEXT" + "\0" + "This is just some text to test for script stream" + "\0";
              byte[] myScriptBA = Encoding.UTF8.GetBytes(myScript);
              IntPtr destPtr;
              hr = pSample.GetPointer(out destPtr);
              Marshal.Copy(myScriptBA, 0, destPtr, myScriptBA.Length);
              pSample.SetActualDataLength(myScriptBA.Length);
      

      Using the GSSF sample, I also set the timestamp for the sample as well as insure that the pSample is released, but the graph only runs for a short time then stops.

      So, not sure where I'm going wrong???

       
      • snarfle

        snarfle - 2009-09-02

        Hmm. Looks right to me.

        How short is "a short time?" Two samples? Or 10 seconds?

        What method are you using to timestamp? SetTime or SetMediaTime?

        If you are putting text on every sample, you probably don't need SetDiscontinuity, but are you setting SetSyncPoint?

        And of course my best tool for diagnosis is, have you looked at an existing file that uses text to see what's different from what you are doing?

         

Log in to post a comment.