<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.iis.net/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Thales&amp;#39; Blog</title><subtitle type="html" /><id>http://blogs.iis.net/thalesc/atom.aspx</id><link rel="alternate" type="text/html" href="http://blogs.iis.net/thalesc/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.iis.net/thalesc/atom.aspx" /><generator uri="http://communityserver.org" version="3.0.20510.895">Community Server</generator><updated>2010-03-15T23:02:00Z</updated><entry><title>How to do Live Streaming with the Smooth Streaming Format SDK</title><link rel="alternate" type="text/html" href="http://blogs.iis.net/thalesc/archive/2011/02/08/how-to-do-live-streaming-with-the-smooth-streaming-format-sdk.aspx" /><id>http://blogs.iis.net/thalesc/archive/2011/02/08/how-to-do-live-streaming-with-the-smooth-streaming-format-sdk.aspx</id><published>2011-02-08T19:17:00Z</published><updated>2011-02-08T19:17:00Z</updated><content type="html">&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;In a previous &lt;/FONT&gt;&lt;A href="http://blogs.iis.net/thalesc/archive/2010/03/15/iis-smooth-streaming-format-sdk-sample-application.aspx" mce_href="http://blogs.iis.net/thalesc/archive/2010/03/15/iis-smooth-streaming-format-sdk-sample-application.aspx"&gt;&lt;FONT size=3 face=Calibri&gt;blog post&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt; I wrote about the sample application that comes with the &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ff402318(v=VS.90).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ff402318(v=VS.90).aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;IIS Smooth Streaming Format SDK&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt;. One important feature missing in that sample is code showing how to do Live Smooth Streaming. The next release of the SDK will correct that and include a new sample application that supports live streaming, yet that release is not planned to hit MSDN in the next couple of months, and in the meanwhile users are facing difficulties trying to add the functionality to their encoders. On top of that the &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ff402319(v=VS.90).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ff402319(v=VS.90).aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;Application Workflow&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt; documentation for the Smooth Streaming Format SDK is a little vague on live streaming. In lieu of that I decided to write this blog post to elaborate on some of the details. This article assumes familiarity with the SDK’s workflow and HTTP.&lt;/FONT&gt;&lt;/P&gt;
&lt;H1 style="MARGIN: 24pt 0in 0pt"&gt;&lt;FONT color=#365f91 size=5 face=Cambria&gt;Setting up the muxer and streams&lt;/FONT&gt;&lt;/H1&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt; 
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;For live streaming the application must put the SDK’s muxer in live mode by setting the SSFMUX_OPTION_LIVE_MODE to TRUE. This must be done before adding streams to the muxer. Basically:&lt;/FONT&gt;&lt;/P&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;BOOL fLiveMode = TRUE;&lt;BR&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;hr = SSFMuxSetOption(&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hMux,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;SSF_MUX_OPTION_LIVE_MODE,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&amp;amp;fLiveMode,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;sizeof&lt;/SPAN&gt;(fLiveMode)&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;);&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;( FAILED(hr) )&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;wprintf( L&lt;SPAN style="COLOR: #a31515"&gt;"Error: 0x%X trying to set Live Mode\r\n"&lt;/SPAN&gt;, hr );&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;goto&lt;/SPAN&gt; done;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt; 
&lt;H1 style="MARGIN: 24pt 0in 0pt"&gt;&lt;FONT color=#365f91 size=5 face=Cambria&gt;Sending the Streams to IIS&lt;/FONT&gt;&lt;/H1&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt; 
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;The Smooth Streaming Live Streaming Protocol requires that each stream sends its header, fragments and index (i.e., the data returned by &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ff402324(v=VS.90).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ff402324(v=VS.90).aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;SSFMuxGetHeader&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt;, &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ff402321(v=VS.90).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ff402321(v=VS.90).aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;SSFMuxProcessOutput&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt; and &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ff402308(v=VS.90).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ff402308(v=VS.90).aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;SSFMuxGetIndex&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt;) to the IIS Server using a HTTP POST request. The URL for the request is specific to each stream and must follow this pattern:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Calibri&gt;&lt;FONT size=3&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;http://&amp;lt;server&amp;gt;/&amp;lt;pubpoint&amp;gt;/Streams(&amp;lt;identifier&amp;gt;)&lt;BR&gt;&lt;/B&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;&lt;BR&gt;The &amp;lt;identifier&amp;gt; part is an arbitrary name chosen by the application that uniquely identifies that stream within the publishing point. It must not contain invalid URL characters, URL separators or parentheses. It can be as simple as just a stream index. The same &lt;B style="mso-bidi-font-weight: normal"&gt;&amp;lt;identifier&amp;gt;&lt;/B&gt; string must be passed as the &lt;/FONT&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;pszSourceFileName&lt;/SPAN&gt;&lt;FONT face=Calibri&gt; field of the SSF_STREAM_INFO struct when adding the stream to the muxer with &lt;/FONT&gt;&lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ff402310(v=VS.90).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ff402310(v=VS.90).aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;SSFMuxAddStream&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt;.&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;The IIS Server is very flexible in terms of how it receives live streams. Fragments can be sent using multiple HTTP POST requests (one per fragment) or a single long running HTTP POST (one per stream). The server automatically filters out-of-order or duplicate fragments to produce the best possible continuous stream. For more details about the server operation, check &lt;/FONT&gt;&lt;A href="http://blogs.iis.net/samzhang/archive/2009/12/16/how-to-build-scalable-and-robust-live-smooth-streaming-server-solutions.aspx" mce_href="http://blogs.iis.net/samzhang/archive/2009/12/16/how-to-build-scalable-and-robust-live-smooth-streaming-server-solutions.aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;this article&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt;.&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;Long running HTTP POST requests should be &lt;/FONT&gt;&lt;A href="http://en.wikipedia.org/wiki/Chunked_transfer_encoding" mce_href="http://en.wikipedia.org/wiki/Chunked_transfer_encoding"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;chunk transfer encoded&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;. This type of HTTP encoding allows applications to start a HTTP request without knowing in advance the entire size of the payload (i.e., the “&lt;/FONT&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;Content-Length&lt;/SPAN&gt;&lt;FONT face=Calibri&gt;”).&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;If you’re going to use &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/aa384273(v=vs.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa384273(v=vs.85).aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;WinHTTP&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt; to handle a long running HTTP POST, keep in mind that although WinHTTP can &lt;I style="mso-bidi-font-style: normal"&gt;receive&lt;/I&gt; data in chunk transfer encoding transparently, when it comes to sending chunked data you have to handle the “chunking” on your own. The first thing to do in this case is to add the “&lt;/FONT&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;Transfer-Encoding: Chunked&lt;/SPAN&gt;&lt;FONT face=Calibri&gt;” header to the HTTP request (note this precludes the need for a “&lt;/FONT&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;Content-Length&lt;/SPAN&gt;&lt;FONT face=Calibri&gt;” header).&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;Here’s a quick code snippet showing how one would go about starting a chunked HTTP POST for a live stream with WinHTTP.&lt;/FONT&gt;&lt;/P&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&lt;BR&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;WCHAR szAdditionalHeaders[] = L&lt;SPAN style="COLOR: #a31515"&gt;"Transfer-Encoding: Chunked"&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;...&lt;BR&gt;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;fResult = WinHttpSendRequest(&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hHttpRequest,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;szAdditionalHeaders,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ARRAYSIZE(szAdditionalHeaders)-1,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;WINHTTP_NO_REQUEST_DATA,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;0,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;0,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;NULL&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;);&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;( !fResult )&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hr = HRESULT_FROM_WIN32( GetLastError() );&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;goto&lt;/SPAN&gt; done;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;/SPAN&gt; 
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;And here’s an example of a function for posting HTTP chunks (assuming WinHTTP is operating in “synchronous” mode):&lt;/FONT&gt;&lt;/P&gt;&lt;SPAN style="LINE-HEIGHT: 115%; FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&lt;BR&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;HRESULT WriteToSmoothStreamOutput(&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;__in HINTERNET hHttpRequest,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;__in_ecount(cbData) LPCVOID pbData,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;__in ULONG cbData )&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;HRESULT hr = S_OK;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;BOOL fResult = FALSE;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;DWORD cbWritten;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&lt;BR&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; COLOR: blue; FONT-SIZE: 9.5pt; mso-ansi-language: PT-BR" lang=PT-BR&gt;char&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt; mso-ansi-language: PT-BR" lang=PT-BR&gt; szHttpChunkHeaderA[32];&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt; mso-ansi-language: PT-BR" lang=PT-BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;char&lt;/SPAN&gt; szHttpChunkFooterA[] = &lt;SPAN style="COLOR: #a31515"&gt;"\r\n"&lt;/SPAN&gt;;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt; mso-ansi-language: PT-BR" lang=PT-BR&gt;&lt;o:p&gt;&lt;BR&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt; mso-ansi-language: PT-BR" lang=PT-BR&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; COLOR: green; FONT-SIZE: 9.5pt"&gt;//&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// Send the HTTP Chunk Transfer Encoding chunk-start mark&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// Observe the use of UTF-8 strings.&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hr = StringCchPrintfA(&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;szHttpChunkHeaderA,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;ARRAYSIZE(szHttpChunkHeaderA),&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;"%X\r\n"&lt;/SPAN&gt;,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;cbData );&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;( FAILED(hr) )&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;goto&lt;/SPAN&gt; done;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&lt;BR&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;fResult = WinHttpWriteData(&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hHttpRequest,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;szHttpChunkHeaderA,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;(DWORD)( strlen(szHttpChunkHeaderA) * &lt;SPAN style="COLOR: blue"&gt;sizeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;char&lt;/SPAN&gt;) ),&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&amp;amp;cbWritten&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;BR&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;( !fResult )&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hr = HRESULT_FROM_WIN32( GetLastError() );&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;goto&lt;/SPAN&gt; done;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// Send the actual chunk data&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&lt;BR&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;( cbData &amp;gt; 0 )&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;fResult = WinHttpWriteData(&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hHttpRequest,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;pbData,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;cbData,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&amp;amp;cbWritten&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;);&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;( FAILED(hr) )&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hr = HRESULT_FROM_WIN32( GetLastError() );&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;goto&lt;/SPAN&gt; done;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// Send the HTTP Chunk Transfer Encoding chunk-end mark&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;fResult = WinHttpWriteData(&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hHttpRequest,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;szHttpChunkFooterA,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;(DWORD)( strlen(szHttpChunkFooterA) * &lt;SPAN style="COLOR: blue"&gt;sizeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;char&lt;/SPAN&gt;) ),&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&amp;amp;cbWritten&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;);&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;( FAILED(hr) )&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hr = HRESULT_FROM_WIN32( GetLastError() );&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;goto&lt;/SPAN&gt; done;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;BR&gt;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;done:&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt;( hr );&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt; 
&lt;H1 style="MARGIN: 24pt 0in 0pt"&gt;&lt;FONT color=#365f91 size=5 face=Cambria&gt;Encoder Workflow&lt;/FONT&gt;&lt;/H1&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt; 
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;The encoding workflow for on-demand and live Smooth Streaming is nearly identical. The main difference is that instead of writing the data returned by &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ff402324(v=VS.90).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ff402324(v=VS.90).aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;SSFMuxGetHeader&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt;, &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ff402321(v=VS.90).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ff402321(v=VS.90).aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;SSFMuxProcessOutput&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt; and &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ff402308(v=VS.90).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ff402308(v=VS.90).aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;SSFMuxGetIndex&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt; to the stream’s destination file, the application posts the data to the stream URL using an HTTP POST (for example using the WriteToSmoothStreamOutput function above).&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;Streams can arrive at the IIS server in any order. Stream headers embed a mini-manifest that lists all the streams participating in the publishing point. The server uses these mini-manifests to wait for all streams to start sending data before it [the server] starts the publishing point. The insertion of this manifest in the stream header can be turned off by setting the muxer option SSF_MUX_OPTION_ENABLE_STREAM_MANIFEST_BOX_FOR_LIVE_MODE to FALSE (the default is TRUE). In this case the server will start the publishing point as soon as the first stream starts, and clients connecting at that time may see only a subset of all streams available. Because of that, this option should only be used when the presentation is generated by multiple encoders running independently.&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;Despite the server flexibility, applications should try to keep the streams in sync with regard to presentation time. Usually this is not a problem for live streams coming from a real-time encoding pipeline (e.g., a webcam). However, applications streaming on-demand content as live must be careful with runaway streams, in particular if these applications receive the media samples as fast as possible from the input pipeline. In this case a low bitrate stream could “play through” much faster than the rest and take over the network bandwidth to send its fragments while other streams fall behind in presentation time. In cases like this the application should try to pace or throttle the streams so they stay relatively in sync (in presentation time).&lt;/FONT&gt;&lt;/P&gt;
&lt;H1 style="MARGIN: 24pt 0in 0pt"&gt;&lt;FONT color=#365f91 size=5 face=Cambria&gt;Ending a Stream&lt;/FONT&gt;&lt;/H1&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt; 
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;When a stream ends, the encoder application calls &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ff402308(v=VS.90).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ff402308(v=VS.90).aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;SSFMuxGetIndex&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt; to obtain the index data for that stream and send it to the server. In “live mode” the “index” is actually an EOS (End Of Stream) packet that tells the server the stream just ended. At this time applications using long running HTTP POST requests should finalize the transmission. To finalize a chunk transfer encoded request one simply sends a 0 length chunk. For the WriteToSmoothStreamOutput function shown above, that means calling it with cbData = 0. Finally, the application can receive the server’s response for the HTTP POST and close the socket. Here’s sample code using WinHTTP (in synchronous mode) to do that.&lt;/FONT&gt;&lt;/P&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// Receive the response from the IIS server for this&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// stream&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;fResult = WinHttpReceiveResponse(&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hHttpRequest,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;NULL&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;);&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;( !fResult )&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hr = HRESULT_FROM_WIN32( GetLastError() );&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;goto&lt;/SPAN&gt; done;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// Get the status code&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;cbStatusCode = &lt;SPAN style="COLOR: blue"&gt;sizeof&lt;/SPAN&gt;(dwStatusCode);&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;fResult = WinHttpQueryHeaders(&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hHttpRequest,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;WINHTTP_HEADER_NAME_BY_INDEX,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&amp;amp;dwStatusCode,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&amp;amp;cbStatusCode,&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;WINHTTP_NO_HEADER_INDEX&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;);&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;( !fResult )&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hr = HRESULT_FROM_WIN32( GetLastError() );&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;goto&lt;/SPAN&gt; done;&lt;BR&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// Handle status code and such&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;...&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// Close the request&lt;BR&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;//&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;WinHttpCloseHandle( hHttpRequest );&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-FAMILY: Consolas; FONT-SIZE: 9.5pt"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt; &lt;/SPAN&gt;&lt;/SPAN&gt;
&lt;H1 style="MARGIN: 24pt 0in 0pt"&gt;&lt;FONT color=#365f91 size=5 face=Cambria&gt;Manifests&lt;/FONT&gt;&lt;/H1&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt; 
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;In Live Smooth Streaming the manifests are generated on-the-fly by the IIS Server when a client connects to the publishing point. This is due to the dynamic and ongoing nature of a live presentation. In that case the encoder does not get to produce any of the manifests. In fact calling &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ff402307(v=VS.90).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ff402307(v=VS.90).aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;SSFMuxGetClientManifest&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt; or &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/ff402320(v=VS.90).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ff402320(v=VS.90).aspx"&gt;&lt;FONT color=#0000ff size=3 face=Calibri&gt;SSFMuxGetServerManifest&lt;/FONT&gt;&lt;/A&gt;&lt;FONT size=3 face=Calibri&gt; when the muxer is in “live mode” is an invalid operation and will return an error code.&lt;/FONT&gt;&lt;/P&gt;
&lt;H1 style="MARGIN: 24pt 0in 0pt"&gt;&lt;FONT color=#365f91 size=5 face=Cambria&gt;Conclusion&lt;/FONT&gt;&lt;/H1&gt;&lt;o:p&gt;&lt;FONT size=3 face=Calibri&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt; 
&lt;P style="MARGIN: 0in 0in 10pt" class=MsoNormal&gt;&lt;FONT size=3 face=Calibri&gt;Live Smooth Streaming is a flexible yet simple protocol. However, the lack of detailed documentation makes its implementation a taxing task. I hope this blog post will help clarify some of the details.&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=4293579" width="1" height="1"&gt;</content><author><name>thalesc</name><uri>http://blogs.iis.net/members/thalesc.aspx</uri></author><category term="Media" scheme="http://blogs.iis.net/thalesc/archive/tags/Media/default.aspx" /></entry><entry><title>IIS Smooth Streaming Format SDK - Sample Application</title><link rel="alternate" type="text/html" href="http://blogs.iis.net/thalesc/archive/2010/03/15/iis-smooth-streaming-format-sdk-sample-application.aspx" /><id>http://blogs.iis.net/thalesc/archive/2010/03/15/iis-smooth-streaming-format-sdk-sample-application.aspx</id><published>2010-03-15T22:02:00Z</published><updated>2010-03-15T22:02:00Z</updated><content type="html">&lt;P&gt;The &lt;A href="http://msdn.microsoft.com/en-us/library/ff402318.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ff402318.aspx"&gt;IIS Smooth Streaming Format SDK&lt;/A&gt; is a library of code for encoder applications to pack media samples in the IIS Smooth Streaming container format (fragmented MP4 format) and generate the corresponding server and client manifests. The output of the SDK can be either written to files for media-on-demand scenarios or pushed to a live publishing point on the IIS server for immediate distribution.&lt;/P&gt;
&lt;P&gt;The SDK’s installation package comes with an example of a basic muxing application. This application uses the SDK to generate the Smooth Streaming format files and manifests from a set of media files encoded in WMA, WMV/VC-1, H.264 or AAC-LC formats. The source code for this application serves as a functional example of how to use the SDK to mux Smooth Streaming content.&lt;/P&gt;
&lt;P&gt;Here’s a very high-level view of the main blocks in the sample application:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.iis.net/controlpanel/blogs/$clip_image0017.jpg" mce_href="$clip_image0017.jpg"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" border=0 src="http://blogs.iis.net/blogs/thalesc/SSFBasicMuxer.jpg" width=467 height=240 mce_src="http://blogs.iis.net/blogs/thalesc/SSFBasicMuxer.jpg"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;The application uses the Microsoft DirectShow (DShow) application programming interface to grab the media types and compressed media samples from the input files. It then feeds those types and samples to the muxer object from the IIS Smooth Streaming Format SDK. Finally, the application takes the resulting fragmented MP4 chunks and manifest data generated by the muxer and writes them to the corresponding files (&lt;I&gt;.ismv, .isma, .ismc&lt;/I&gt; or &lt;I&gt;.ism&lt;/I&gt;).&lt;/P&gt;
&lt;P&gt;Note: DirectShow does not ship with H.264 or AAC-LC filters. To enable these formats in the sample application you will need to install DShow filters for them.&lt;/P&gt;
&lt;H3&gt;1. Parse the input parameters&lt;/H3&gt;
&lt;P&gt;The application takes a text file as input. This text file contains a list of the media files and corresponding bitrates to mux, one media file per line. The format of each line is:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;lt;bitrate&amp;gt; , &amp;lt;filename&amp;gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;For example, the text file could contain a list like this:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;904000, Movie_1.wmv &lt;BR&gt;760000, Movie_2.wmv &lt;BR&gt;580000, Movie_3.wmv &lt;BR&gt;77000, Sound_1.wma&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;I will not go into the details of how the input file is parsed, but I should explain why the sample application requires users to input the bitrates explicitly. In theory the application could get the bitrate property directly from DShow, but the fact is that exposing this property is optional for DShow filters, and not every one of them does it, so to be more generic while maintaining the code simple the application requires the bitrate information as an explicit parameter.&lt;/P&gt;
&lt;H3&gt;2. Setup the media pipeline&lt;/H3&gt;
&lt;P&gt;The next step is to set up the input pipelines in a DShow graph, one branch for each input file. The pipeline will output the compressed elementary stream media samples to the application which will in turn feed them to the muxer. For each branch of the pipeline the application uses a custom “sample grabber” DShow filter with a simplified callback interface to receive the compressed samples. The default sample grabber filter that ships with the DirectShow API does not handle all the media types the application targets, hence the need for a custom filter. This custom filter comes in the &lt;I&gt;dshowhlp.lib&lt;/I&gt; static library that accompanies the sample code. This library is intended for use in this example only and should not be used or re-distributed in any other applications.&lt;/P&gt;
&lt;P&gt;The grabber filter has a single input pin that accepts any media type. Samples received in this pin are relayed to the application’s callback.&lt;/P&gt;
&lt;P&gt;The interesting code to look at here is the StreamContext_AddToDShowGraph function, which sets up the DShow branch of the pipeline for each input file. Let’s take a look.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#808080 face="Courier New"&gt;//------------------------------------------------------------------------------ &lt;BR&gt;HRESULT StreamContext_AddToDShowGraph( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; __inout StreamContext* pCtx, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; __in IGraphBuilder *pIGraph ) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HRESULT hr = S_OK; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IBaseFilter* pBaseFilter = NULL; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPGI* pGrabber = NULL;&lt;/FONT&gt; &lt;BR&gt;&lt;BR&gt;First we create a grabber filter for the file and stick it in the DShow graph. PGI_CreatedInstance is defined in &lt;I&gt;dshowhlp.lib&lt;/I&gt;. &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#808080 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = PGI_CreateInstance( IID_IPGI, (void**)&amp;amp;pGrabber ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf( "Error 0x%08x: failed to create sample grabber filter", hr ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = pGrabber-&amp;gt;QueryInterface( IID_IBaseFilter, (PVOID*)&amp;amp;pBaseFilter); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = pIGraph-&amp;gt;AddFilter( pBaseFilter, NULL ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf( "Error 0x%08x: failed to add sample grabber to graph", hr ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Next we ask the DShow graph to render the input file. This means adding that file to the pipeline. DShow will instantiate the proper source filter for the file’s type and try to pull the necessary filters to complete the pipeline for that source. Since the grabber is preloaded in the graph, DShow will try it first, and because the grabber accepts all media types, DShow will go ahead and connect the source’s first output pin to the grabber’s only input pin.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Note this implies the source can have only one output pin. A limitation of this code example is it requires the input files to be single-stream. If there more than one media stream per file, let’s say an audio and video stream, DShow will connect the first to the grabber filter and then try to load default filters to connect the remaining streams. This can result in weird behavior like, for instance, the tool playing a stray video stream on the screen.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;To support multiple streams per file would require constructing the pipeline programmatically. In other words, we would have to instantiate the source filter, enumerate its output pins, and connect each to a grabber filter. That would complicate the code more than its purpose.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#808080 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = pIGraph-&amp;gt;RenderFile( pCtx-&amp;gt;szInputFileName, NULL ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf( "Error 0x%08x: failed trying to open file in DShow graph", hr ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (FALSE == IsConnected(pBaseFilter)) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf( "Error 0x%08x: failed to connect sample grabber", hr ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt; &lt;BR&gt;&lt;BR&gt;Once the new branch of the pipeline is connected, we register the application’s callback in the grabber filter. That’s the callback the grabber will call to deliver the compressed samples.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#808080 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = pGrabber-&amp;gt;set_Callback2( HandleSampleHook, pCtx ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf( "Error 0x%08x: failed to set the IPGI callback", hr ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Finally we extract the media type of the new branch, which we’ll need later to setup the SDK’s muxer. I won’t go into detail on how to get that media type. Hopefully the code is self-explanatory.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#808080 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = StreamContext_SetTypeInfoFromRenderer( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pCtx, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pBaseFilter ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;done: &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SAFE_RELEASE( pBaseFilter ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SAFE_RELEASE( pGrabber ); &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ( hr ); &lt;BR&gt;}&lt;/FONT&gt; &lt;BR&gt;&lt;FONT color=#808080 face="Courier New"&gt;//------------------------------------------------------------------------------&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;H3&gt;&amp;nbsp;&lt;/H3&gt;
&lt;H3&gt;3. Create the SSF muxer and set it up&lt;/H3&gt;
&lt;P&gt;Once the input pipeline is set up, the next step is to instantiate the muxer object from the IIS Smooth Streaming Format SDK. Let’s look at the code.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;First we use SSFMuxCreate to create the muxer.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#808080 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = SSFMuxCreate( &amp;amp;hSSFMux ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf( "Error 0x%08x: Failed to create SSF muxer\n", hr ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;/FONT&gt;&lt;BR&gt;Then we configure the basic options.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#808080 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; UINT64 timeScale = 10000000; // time scale in HNS &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = SSFMuxSetOption( hSSFMux, SSF_MUX_OPTION_TIME_SCALE, &amp;amp;timeScale, sizeof(timeScale) ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf( "Error 0x%08x: Failed to set SSF_MUX_OPTION_TIME_SCALE\n", hr ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BOOL fVariableBitRate = TRUE; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = SSFMuxSetOption( hSSFMux, SSF_MUX_OPTION_VARIABLE_RATE, &amp;amp;fVariableBitRate, sizeof(fVariableBitRate) ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf( "Error 0x%08x: Failed to set SSF_MUX_OPTION_VARIABLE_RATE\n", hr ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Finally we add one stream in the muxer for each input file. We need to add all streams we intended to mux upfront. &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#808080 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Add streams to the muxer &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for( ULONG i = 0; i &amp;lt; cStreams; ++i ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = AddStreamToMux( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;rgStreams[i], &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hSSFMux, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( AUDIO == rgStreams[i].eStreamType ) ? cAudioStreams++ : cVideoStreams++ ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf( "Error 0x%08x: Failed to set add stream to mux\n", hr ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rgStreamIndices[i] = rgStreams[i].dwStreamIndex; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt; &lt;BR&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Let’s take a look in AddStreamToMux to see what it does:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#808080 face="Courier New"&gt;//------------------------------------------------------------------------------ &lt;BR&gt;HRESULT AddStreamToMux( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; __inout StreamContext* pCtx, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; __in SSFMUXHANDLE hSSFMux, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; __in ULONG iStream ) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HRESULT hr = S_OK; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SSF_STREAM_INFO streamInfo; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; memset( &amp;amp;streamInfo, 0, sizeof(streamInfo) ); &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pCtx-&amp;gt;hSSFMux = hSSFMux; &lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;Here we format the archive name for the stream. We use “&lt;I&gt;Audio&amp;lt;n&amp;gt;.isma&lt;/I&gt;” for audio streams and “&lt;I&gt;Video&amp;lt;n&amp;gt;.ismv&lt;/I&gt;” for video streams. Basically that’s the name of the ISM file to contain the media stream. The current version of the SDK allows one stream per ISM file only. Although the SDK does not write the fragmented MP4 data to the files directly, the data may contain offsets that impose assumptions on how the data is persisted to files, hence the limitation. The next version of the SDK (Beta 2) shall have API to synchronize offsets and give more freedom to the application to merge multiple streams in one ISM.&lt;FONT color=#808080 face="Courier New"&gt; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( 0 &amp;gt; swprintf_s( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pCtx-&amp;gt;szArchiveName, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MAX_PATH, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ( pCtx-&amp;gt;eStreamType == AUDIO ) ? L"Audio%d.isma" : L"Video%d.ismv", &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; iStream ) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = E_UNEXPECTED; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;Next we choose how long each fragment will be. For simplicity we’ll fix the value at 5 seconds for audio streams and 2 seconds for video streams. We select this value here for convenience, but note that it’s not used directly by the SDK’s muxer. Instead, we’ll use it later in the callback function to decide where to split the fragments.&lt;FONT color=#808080 face="Courier New"&gt; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( pCtx-&amp;gt;eStreamType == AUDIO ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pCtx-&amp;gt;rtChunkDuration = 50000000; // 5 seconds in hns units &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pCtx-&amp;gt;rtChunkDuration = 20000000; // 2 seconds in hns units &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; streamInfo.streamType = pCtx-&amp;gt;eStreamType; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; streamInfo.dwBitrate = pCtx-&amp;gt;bitrate; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; streamInfo.pszStreamName = pCtx-&amp;gt;szArchiveName; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; streamInfo.pTypeSpecificInfo = pCtx-&amp;gt;pbTypeInfo; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; streamInfo.cbTypeSpecificInfo = pCtx-&amp;gt;cbTypeInfo; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; streamInfo.wLanguage = MAKELANGUAGE('e','n','n'); &lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;Finally we add the stream to the muxer with SSFMuxAddStream. If successful, the API returns a stream index that we use to refer to this particular stream for now on.&lt;FONT color=#808080 face="Courier New"&gt; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = SSFMuxAddStream( hSSFMux, &amp;amp;streamInfo, &amp;amp;pCtx-&amp;gt;dwStreamIndex ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;done: &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return( hr ); &lt;BR&gt;} &lt;BR&gt;//------------------------------------------------------------------------------&lt;/FONT&gt; &lt;BR&gt;&lt;FONT face="Courier New"&gt;&lt;FONT color=#808080&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;H3&gt;4. Get the Smooth Streaming headers&lt;/H3&gt;
&lt;P&gt;The next step is to get the headers for each stream and write them to the corresponding &lt;I&gt;.ismv&lt;/I&gt; or &lt;I&gt;.isma&lt;/I&gt; file. Note that SSFMuxGetHeader takes a list of stream indices. This is a provision to allow applications to merge multiple streams into a single &lt;I&gt;.ismv&lt;/I&gt; or &lt;I&gt;.isma&lt;/I&gt; file. However, due to the limitations mentioned before, that’s not fully supported in the Beta 1 version of the SDK. &lt;/P&gt;
&lt;P&gt;Note that the sample application will re-write the headers later when it finalizes the files. This needs to be done because the contents of the headers change as the muxer processes media samples. In fact, the only reason why the sample application requests the headers at this early point is to reserve room for the final headers in the files. The contents of the headers change, but their total lengths do not. Later the application can just re-write the final headers without the need to shift the contents of the files.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;FONT color=#808080 face="Courier New"&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for( ULONG i = 0; i &amp;lt; cStreams; ++i ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = SSFMuxGetHeader( hSSFMux, &amp;amp;rgStreams[i].dwStreamIndex, 1, &amp;amp;outputBuffer ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf( "Error 0x%08x: Failed to get FMP4 header\n", hr ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = StreamContext_WriteDataToFile( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;rgStreams[i], &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; L"wb", &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; outputBuffer.pbBuffer, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; outputBuffer.cbBuffer ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf( "Error 0x%08x: Failed to write header to FMP4 file\n", hr ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt; &lt;BR&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;H3&gt;&amp;nbsp;&lt;/H3&gt;
&lt;H3&gt;5. Mux the Media Streams&lt;/H3&gt;
&lt;P&gt;It’s time to run the DShow graph and feed the incoming compressed samples into the muxer. That’s controlled by the Play function, a regular DShow run loop that starts the graph to play back the input streams through the grabber filters and then dispatches events from the graph until the playback ends. &lt;/P&gt;
&lt;P&gt;The important code to look at here is the StreamContext_HandleSample function. This is the function that receives the samples and feeds them into the muxer. First let’s take a look at HandleSampleHook, the callback that the application hooks up to each grabber filter. This function maps the callback application data back to the StreamContext structure that binds an input stream in the graph to an output stream in the muxer.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#808080 face="Courier New"&gt;//------------------------------------------------------------------------------ &lt;BR&gt;HRESULT WINAPI HandleSampleHook( __in void* pCtx, __in_opt IMediaSample* pSample ) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; StreamContext* pStreamCtx = (StreamContext*)pCtx; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return( StreamContext_HandleSample( pStreamCtx, pSample ) ); &lt;BR&gt;} &lt;BR&gt;//------------------------------------------------------------------------------&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Back to StreamContext_HandleSample, it feeds samples into the muxer by calling ProcessInput. If a fragment is complete, the function calls ProcessOutput to close that fragment and extract its data. Note that it is up to the application to decide when to close a fragment. This does not mean the application can close a fragment at any sample. The fragmented MP4 format requires fragments to contain full GOPs (Group of Pictures), yet the SDK does not attempt to detect these boundaries in order to enforce them – that is a responsibility of the application.&lt;/P&gt;
&lt;P&gt;StreamContext_HandleSample uses the IsSyncPoint method of the incoming sample’s IMediaSample interface to establish GOP boundaries. Note, however, that all IsSyncPoint really does is to tell if the sample is an I-frame or not, yet not every I-frame needs to be a GOP boundary (unless the content was encoded that way). This implies the sample application only works with input files that have been encoded such that every I-frame is in its own closed GOP with no addition I-frames. Some H.264 content may contain an IDR frame at the beginning of the CVS (coded-video sequence), but it can also contain I-frames in the CVS prior to the next IDR frame. The sample application may generate invalid &lt;I&gt;.ismv&lt;/I&gt; files for input files that are encoded with multiple I-frames in a GOP. This is a limitation of this example in particular. The SDK can handle the scenario correctly provided the application makes sure no GOP gets split in multiple fragments.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#808080 face="Courier New"&gt;&lt;BR&gt;//------------------------------------------------------------------------------ &lt;BR&gt;HRESULT StreamContext_HandleSample( &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; __in StreamContext* pCtx, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; __in_opt IMediaSample* pSample ) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HRESULT hr = S_OK; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BOOL fProcessOutput = FALSE; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; REFERENCE_TIME rtStartTime = 0; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; REFERENCE_TIME rtStopTime = 0; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Verify the conditions to pull a fragment for this stream &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( NULL == pSample ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // A null sample means the stream has ended. &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Pull the last fragment then. &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fProcessOutput = TRUE; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Pull a fragment if the sample is a sync point &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // and the fragment duration has been reached &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = pSample-&amp;gt;GetTime( &amp;amp;rtStartTime, &amp;amp;rtStopTime ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pCtx-&amp;gt;rtChunkCurrentTime = rtStartTime; &lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;Apart from looking for sync-point samples, the function also uses the fragment’s accumulated duration to decide when to close the fragment. A fragment gets closed right before the first sync-point sample that exceeds the expected duration (which in this example is 5 seconds for audio streams and 2 seconds for video streams). The sample that triggers this will be carried over to the next fragment.&lt;/P&gt;
&lt;P&gt;IMPORTANT: Before closing the current fragment we must call SSFMuxAdjustDuration with the current sample’s start time to update the duration of the fragment that is about to get closed. This step is necessary because certain media types do not provide accurate duration for the media samples, and to find a sample’s correct duration one needs to look at the start time of the sample that comes next. In cases like this the muxer does not&amp;nbsp;know how to compute the fragment’s total duration solely from the media samples in that fragment; the muxer also needs the start time of the very next sample right after the last one that went in the fragment.&lt;/P&gt;
&lt;P&gt;The SSFMuxAdjustDuration API needs to be called only on fragment boundaries.&lt;/P&gt;
&lt;P&gt;Of course the other condition that causes a segment to get closed is when the end-of-stream arrives. This is indicated by a null pSample pointer.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#808080 face="Courier New"&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( ( S_OK == pSample-&amp;gt;IsSyncPoint() ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;&amp;amp; ( pCtx-&amp;gt;rtChunkCurrentTime - pCtx-&amp;gt;rtChunkStartTime &amp;gt;= pCtx-&amp;gt;rtChunkDuration ) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fProcessOutput = TRUE; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = SSFMuxAdjustDuration( pCtx-&amp;gt;hSSFMux, pCtx-&amp;gt;dwStreamIndex, rtStartTime ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;Calling SSFMuxProcessOutput closes the current fragment and returns a buffer with the data to be appended to the corresponding &lt;I&gt;.ismv&lt;/I&gt; or &lt;I&gt;.isma&lt;/I&gt; file. The content of the buffer is valid only until the next call to SSFMuxProcessOutput for the same muxer. Applications should not hold this buffer more than necessary. If needed, applications must copy the data to a separate buffer.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#808080 face="Courier New"&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Pull a fragment if the conditions require &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( fProcessOutput ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SSF_BUFFER outputBuffer; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = SSFMuxProcessOutput( pCtx-&amp;gt;hSSFMux, pCtx-&amp;gt;dwStreamIndex, &amp;amp;outputBuffer ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf( "Stream #%d TS=%I64d Duration=%I64d\n", &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pCtx-&amp;gt;dwStreamIndex, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; outputBuffer.qwTime, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; outputBuffer.qwDuration ); &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ++pCtx-&amp;gt;dwChunkIndex; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = StreamContext_WriteDataToFile( pCtx, L"ab", outputBuffer.pbBuffer, outputBuffer.cbBuffer ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pCtx-&amp;gt;fChunkInProgress = FALSE; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/STRONG&gt;The next step is to feed the sample into the muxer. That’s done through the SSFMuxProcessInput API. If a fragment has just been closed in the previous portion of the code, or if this is the very first sample for this stream, the API will start a new fragment for that stream.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#808080 face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Process the input sample if any &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( NULL != pSample ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SSF_SAMPLE inputSample = { 0 }; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BYTE* pbSampleData = NULL; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = pSample-&amp;gt;GetPointer( &amp;amp;pbSampleData ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inputSample.qwSampleStartTime = (UINT64)rtStartTime; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inputSample.pSampleData = pbSampleData; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inputSample.cbSampleData = pSample-&amp;gt;GetActualDataLength(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inputSample.flags = SSF_SAMPLE_FLAG_START_TIME; &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( pCtx-&amp;gt;fSampleDurationIsReliable ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inputSample.qwSampleDuration = rtStopTime - rtStartTime; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; inputSample.flags |= SSF_SAMPLE_FLAG_DURATION; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( !pCtx-&amp;gt;fChunkInProgress ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pCtx-&amp;gt;rtChunkStartTime = rtStartTime; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pCtx-&amp;gt;fChunkInProgress = TRUE; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = SSFMuxProcessInput( pCtx-&amp;gt;hSSFMux, pCtx-&amp;gt;dwStreamIndex, &amp;amp;inputSample ); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if( FAILED(hr) ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; goto done; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&lt;BR&gt;done: &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp; return ( hr ); &lt;BR&gt;} &lt;BR&gt;//------------------------------------------------------------------------------&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;It is not necessary to send the end-of-stream signal back to the main loop in the Play function. The DShow graph does that automatically once all input streams reach the end.&lt;/P&gt;
&lt;H4&gt;&amp;nbsp;&lt;/H4&gt;
&lt;H3&gt;6. Finalize the &lt;I&gt;.ismv&lt;/I&gt; and &lt;I&gt;.isma&lt;/I&gt; files&lt;/H3&gt;
&lt;P&gt;To finalize a &lt;I&gt;.ismv&lt;/I&gt; or &lt;I&gt;.isma&lt;/I&gt; file the application needs to update the header and append the index that corresponds to that file.&lt;/P&gt;
&lt;P&gt;Early on the application had already written a placeholder header to each file to reserve room for the final header. Since only the contents of the header changed during muxing, but not its total length, all the application has to do now is to call SSFMuxGetHeader once again to get the header for each individual stream and rewrite the data to the beginning of the file corresponding to that stream. The same goes for the index, the only difference is that the application uses SSFMuxGetIndex to get it and appends the data to the end of the file. The index contains indexing information for all the fragments in that file plus the closing MP4 atoms that mark the end of the file.&lt;/P&gt;
&lt;P&gt;Note that SSFMuxGetIndex is similar to SSFMuxGetHeader in the sense that both can be used to obtain an index (or header) that combines multiple streams in a single file. As mentioned before, however, the Beta1 version of the SDK does not fully support the scenario due to other limitation.&lt;/P&gt;
&lt;H3&gt;&amp;nbsp;&lt;/H3&gt;
&lt;H3&gt;7. Generate the Manifests&lt;/H3&gt;
&lt;P&gt;The last step in the sample application is to emit the server and client manifests. To get those pieces of data the application calls SSFMuxGetServerManifest and SSFMuxGetClientManifest, and then it writes the data to the corresponding manifest files.&lt;/P&gt;
&lt;P&gt;Note that although the SDK has a Unicode API set, SSFMuxGetServerManifest and SSFMuxGetClientManifest in particular return the manifest text in ASCII format. This is to allow the application to write the data verbatim to the manifest files without the need for UTF8 or UTF16 encoding.&lt;/P&gt;
&lt;P&gt;Another important thing to notice is that SSFMuxGetServerManifest takes a list of streams in the same way that SSFMuxGetHeader and SSFMuxGetIndex do. However, in this case the application does call the API passing in the entire set of streams. This is because the server manifest is supposed to contain the entire set.&lt;/P&gt;
&lt;H3&gt;&amp;nbsp;&lt;/H3&gt;
&lt;H3&gt;8. Conclusion&lt;/H3&gt;
&lt;P&gt;Despite being a simple tool, the basic muxer sample application is a good example of the workflow that encoder applications need to follow when using the IIS Smooth Streaming Format SDK to generate on-demand Smooth Streaming files.&lt;/P&gt;&lt;img src="http://blogs.iis.net/aggbug.aspx?PostID=3732825" width="1" height="1"&gt;</content><author><name>thalesc</name><uri>http://blogs.iis.net/members/thalesc.aspx</uri></author><category term="Media" scheme="http://blogs.iis.net/thalesc/archive/tags/Media/default.aspx" /></entry></feed>