THe HTTP Proxy BUG

Feb 18, 2014 at 7:00 AM
hi the work recent updates really good, But found a problem
If use a proxy to access the live stream , it will not be parsed correctly.
If you need an example proxy, I will send you the http url.
Coordinator
Feb 18, 2014 at 8:47 AM
What platform are you using and what kind of proxy? Are you seeing anything funny in the debugger's output window? Did this work before all those changes I pushed?

Send a PM if you don't want to share the URL with the world. If you have a specific configuration that might be difficult to replicate, then a Fiddler2 trace (.saz file) could be useful.
Feb 18, 2014 at 9:03 AM
it works good before the changes.
it's a php proxy. it contains some url jump. here is the url "http://115.28.165.209:8081/fengyun.php?btv6.htm" if i use the Really direct url ,it can play well.
Coordinator
Feb 18, 2014 at 10:16 AM
The code used to assume M3U8 if it couldn't detect anything better from the URL or the headers. This is no longer the case and I'm not sure what the default behavior should be. If nothing else, it should probably be configurable.

In this case, the post-redirect URL has a ".m3u8" and the post-redirect URL is what it should be looking at.

I may clean things up a bit further since IWebContentTypeDetector.GetContentTypeAsync() should probably return a class for this purpose instead of a 3-tuple.

The detection logic first looks at file extension in the URL. If that content type is recognized, it will return that type. Otherwise it will first try a HEAD and then a GET to the supplied URL. If the the file extension in the URL after all redirects is recognized, then that content type is returned. Finally, it will look at the Content-Type in the HTTP headers to see if that is recognized. By default, the detection is managed by WebContentTypeDetector using ContentTypeDetector (through IWebContentTypeDetector and IContentTypeDetector, respectively), from the types in SM.Media.Content.ContentTypes.

In this case, the original URL has the extension ".php", which is not recognized. The redirected URL is ".m3u8", which is recognized by the code after the changes I just pushed. The Content-Type returned from the server is "application/octet-stream", which is not recognized (it would need to be "application/vnd.apple.mpegurl" or "application/x-mpegURL" to be recognized that way).

Could you give it a try with the changes in 1fa7476a6fa3 and see if that fixes the problem for you?

Thanks.
Feb 18, 2014 at 10:51 AM
Yes It work well.But switch stream cause problems..... Maybe the header content-Type cause the bug?
Coordinator
Feb 18, 2014 at 11:47 AM
It should only depend on the stream. I would suspect something else is going wrong. What problems are you seeing when you switch streams?

One way to see if your problem has something to do with content type detection is with the HlsView.WP8 app (assuming you are targeting Windows Phone 8). Add a
#define STREAM_SWITCHING
to the top of HlsView.WP8\MainPage.xaml.cs (before the using statements). Replace the contents of the "Sources" array with the URLs you are interested in, then run the program with the debugger attached. It should cycle through each of the URLs in the "Sources" array, playing each for about 15 seconds. This should work just as well with the Player Framework plugin, but HlsView.WP8 happens to already have timer-based source switch code.

You should see stuff like,
WebContentTypeDetector.GetContentTypeAsync() url header http://115.28.165.209:8081/fengyun.php?btv6.htm type M3U8 (application/vnd.apple.mpegurl)
in the debugger's output window (Debug -> Windows -> Output) and that should show how the streams are getting detected.

You should see the nearly the same data for your application when built against the debug SM.*.DLLs and run with a debugger attached.
Feb 18, 2014 at 12:11 PM
TsMediaManager.OpenMediaAsync() state OpenMedia
MediaStreamFascade.MediaManagerOnStateChange() to Opening:
MediaElement State: Opening
WebContentTypeDetector.GetContentTypeAsync() url header http://115.28.165.209:8081/fengyun.php?btv6.htm type M3U8 (application/vnd.apple.mpegurl)
PlaylistSegmentManager.ReadSubList (2014/2/18 21:07:20 +08:00)
PlaylistSegmentManager.UpdatePlaylist: playlist http://imgwnas0wnas5wnasfs4.m5wscdn-h.kukuplay.com/ts/btv6_1383477501945/playlist.m3u8?sn=574434a3b967f6dd3ed2a830ab15fbc7DNDcxNDhoNHA1bDRxD&nocache=33dfb6f81c89424783025056d8483d66 loaded with 10 entries in 00:00:00.5241972. index: -1 dynamic: True expires: 00:00:20 (2014/2/18 21:07:21 +08:00)
WebContentTypeDetector.GetContentTypeAsync() url ext http://imgwnas0wnas5wnasfs4.m5wscdn-h.kukuplay.com/ts/btv6_1383477501945/1392725610.ts type MPEG-2 Transport Stream (video/MP2T)
TsMediaManager.InitializeMediaParser() for MPEG-2 Transport Stream (video/MP2T)
++++ Starting http://imgwnas0wnas5wnasfs4.m5wscdn-h.kukuplay.com/ts/btv6_1383477501945/1392725610.ts at 2014/2/18 21:07:21 +08:00. Total memory: 3.20 MiB
PlaylistSegmentManager.ReadSubList (2014/2/18 21:07:41 +08:00)

PlaylistSegmentManager.UpdatePlaylist: playlist http://imgwnas0wnas5wnasfs4.m5wscdn-h.kukuplay.com/ts/btv6_1383477501945/playlist.m3u8?sn=574434a3b967f6dd3ed2a830ab15fbc7DNDcxNDhoNHA1bDRxD&nocache=33dfb6f81c89424783025056d8483d66 loaded with 12 entries in 00:00:01.4119290. index: 1 dynamic: True expires: 00:00:20 (2014/2/18 21:07:42 +08:00)
MediaStreamFascade.SetMediaSourceAsync(http://ppu.17kds.net/live/5/30/887d4d23ee894ceb8f5f457fa24f3e97.m3u8?type=tv)
MediaStreamFascade.OpenMediaAsync()
MediaStreamFascade.CloseMediaAsync()
TsMediaManager.CloseAsync()
MediaStreamFascade.MediaManagerOnStateChange() to Closing:
TsMediaManager.CloseAsync() calling readerManager.StopAsync()
MediaElement State: Opening
TsMediaManager.CloseAsync() calling _mediaStreamSource.CloseAsync()
TsMediaStreamSource.CloseAsync(): open 0 drain RanToCompletion
TsMediaManager.CloseAsync() closing readers
.....
.....
......
TsMediaManager.CloseAsync() readers closed
TsMediaManager.CloseAsync() calling _mediaElementManager.CloseAsync()
TsMediaStreamSource.CloseMedia()
Media CloseMediaCalled: Opening -> Closing at 2014/2/18 21:08:05 +08:00
TsMediaStreamSource.CloseMediaHandler()
TsMediaManager.CloseMedia()
TsMediaManager.CloseAsync()
MediaElement State: Closed
TsMediaManager.CloseAsync() returned from _mediaElementManager.CloseAsync()
TsMediaManager.CloseAsync() waiting for _mediaStreamSource.CloseAsync()
TsMediaManager.CloseAsync() finished _mediaStreamSource.CloseAsync()
TsMediaManager.DisposeReaders()
TsMediaManager.CleanupReaders() completed
TsMediaManager.CloseAsync() completed
...
....
TsMediaManager.Dispose()
TsMediaManager.CloseAsync()
MediaElement State: Closed
MediaStreamFascade.MediaManagerOnStateChange() to Closed:
MediaStreamFascade.Stop()
TsMediaStreamSource.Dispose()
MediaElement State: Closed
Media DisposeCalled: Closing -> Idle at 2014/2/18 21:08:06 +08:00
...
...
MediaStreamFascade.CloseMediaAsync() completed
Media MediaStreamSourceAssigned: Idle -> Assigned at 2014/2/18 21:08:06 +08:00
MediaElement State: Opening
TsMediaStreamSource.OpenMediaAsync()
Media OpenMediaAsyncCalled: Assigned -> Opening at 2014/2/18 21:08:06 +08:00
TsMediaManager.OpenMedia()
TsMediaManager.OpenMedia() handler
TsMediaManager.OpenMediaAsync() state OpenMedia
WebContentTypeDetector.GetContentTypeAsync() url ext http://ppu.17kds.net/live/5/30/887d4d23ee894ceb8f5f457fa24f3e97.m3u8?type=tv type M3U8 (application/vnd.apple.mpegurl)
MediaStreamFascade.CloseMediaAsync()
TsMediaManager.CloseAsync()
TsMediaManager.CloseAsync() calling _mediaStreamSource.CloseAsync()
MediaElement State: Opening
TsMediaStreamSource.CloseAsync(): open 0 drain WaitingForActivation
TsMediaManager.CloseAsync() calling _mediaElementManager.CloseAsync()
MediaStreamFascade.MediaManagerOnStateChange() to Closing:
TsMediaStreamSource.CloseMedia()
Media CloseMediaCalled: Opening -> Closing at 2014/2/18 21:08:07 +08:00
TsMediaStreamSource.CloseMediaHandler()
TsMediaManager.CloseMedia()
MediaElement State: Closed
TsMediaManager.CloseAsync() returned from _mediaElementManager.CloseAsync()
TsMediaManager.CloseAsync() waiting for _mediaStreamSource.CloseAsync()
TsMediaManager.CloseAsync() finished _mediaStreamSource.CloseAsync()
TsMediaManager.CloseAsync() completed
TsMediaManager.Dispose()
TsMediaManager.CloseAsync()
MediaStreamFascade.MediaManagerOnStateChange() to Closed:
MediaStreamFascade.Stop()
MediaElement State: Closed
MediaElement State: Closed
MediaElement State: Closed
....
....
AsyncFifoWorker.Worker() work should not throw exceptions: One or more errors occurred.
TsMediaManager.CloseAsync()
TsMediaStreamSource.Dispose()
Media DisposeCalled: Closing -> Idle at 2014/2/18 21:08:15 +08:00
...
...
MediaStreamFascade.CloseMediaAsync() completed
MediaStreamFascade.CloseMediaAsync()
MediaStreamFascade.CloseMediaAsync() completed
Feb 18, 2014 at 3:19 PM
Oh That case maybe appeared when project debug mode. if only run the work by not debug mode , the switch stream work well.
Coordinator
Feb 19, 2014 at 4:02 AM
I think that second URL (ppu.17kds.net) is having trouble because it sometimes takes a really long time to download the playlist. There is a quirk in phonesm's startup code such that the first two requests for dynamic playlists are very close together. I saw some requests take over two minutes (!). Some servers do take extra long to respond if they think the client is reading the playlist too often, but I haven't seen one be this picky right off the bat.

I'm not sure what it would take to change the startup playlist double-download into a single download. IIRC, the code that looks at the playlists to determine what kind of parser to create (e.g., a given M3U8 media playlist may consist of .ts, .aac, or .mp3 segments and each needs a different kind of IMediaParser) isn't talking to the code that manages the playlist during playback. I may be able to take a look later.
Coordinator
Feb 20, 2014 at 10:21 AM
Scratch the "IIRC". I did not remember correctly. There is no good reason for that occasional double read. It should only happen if the top level URL points to a Media Playlist (i.e., one containing segments, not other playlists).

I'm thinking that the whole responsibility for managing the playlists (both Master playlists and Media playlists) should move to PlaylistSegmentManager. This is a bit easier to do now that I've rearranged the code. Such a change will be necessary for dealing with server redundancy and bandwidth switching anyway.
Coordinator
Feb 25, 2014 at 3:45 PM
Could you see if the changes in 2993f9d20574 get the ppu.17kds.net stream working?

Thanks.
Feb 25, 2014 at 4:49 PM
Yes It works well,
But There will be some problems when switching urls;
MayBe my urls is not same type;
here is my two urls
"http://ppu.17kds.net/live/5/30/238baa4ac12f427896cecf12234159ef.m3u8?type=tv",
        "http://115.28.165.209:8081/fengyun.php?gansuweishi.htm" 
No problem playing any one of the individual,but the following code will have problems when switching


GC.Collect();
                           GC.WaitForPendingFinalizers();
                           GC.Collect();

                           var gcMemory = GC.GetTotalMemory(true).BytesToMiB();

                           var source = Sources[_count];

                           Debug.WriteLine("Switching to {0} (GC {1:F3} MiB App {2:F3}/{3:F3}/{4:F3} MiB)", source, gcMemory,
                               DeviceStatus.ApplicationCurrentMemoryUsage.BytesToMiB(),
                               DeviceStatus.ApplicationPeakMemoryUsage.BytesToMiB(),
                               DeviceStatus.ApplicationMemoryUsageLimit.BytesToMiB());

                           InitializeMediaStream();

                           _mediaStreamFascade.Source = null == source ? null : new Uri(source);

                           if (++_count >= Sources.Length)
                               _count = 0;

                           _positionSampler.Start();
Coordinator
Feb 25, 2014 at 6:07 PM
Both seem to work if I increase the timer period to 25 seconds. I think the cleanup of the old stream plus startup of the new one often is longer than the 15 second period.

There may also be a race when a stream is changed during an open. I have tested for this, but I haven't tested with something that takes a really long time to start. I'll see about rigging up a test where the switch timer's timeout changes.

I also see that HlsView's error message isn't getting cleared when it should.
Coordinator
Feb 25, 2014 at 6:10 PM
I'm not saying there isn't a problem. But I think the interesting question is if the only thing going on is that the time between when a stream is selected and when it starts playing is taking longer than it should.
Feb 26, 2014 at 5:26 PM
Please look this url "http://222.73.28.112/player/index_live_ios2_child.meta?channel_id=78&bit_rate=450", why it can't play well? maybe the content-type?
Coordinator
Feb 27, 2014 at 9:56 AM
Edited Feb 27, 2014 at 10:06 AM
Yes, there was a problem with the content type. It should be better in 62ab690b0937.

You may want to set MediaStreamFascade.ContentType to ContentTypes.TransportStream anyway if you know that a URL is an M3U8 playlist but doesn't have a URL with a ".m3u8" extension. That will save an extra HTTP HEAD (or if the HEAD fails, a HEAD followed by a GET) on the network when starting playback.

However, that is an interesting stream for other reasons. It seems to start every transport stream segment with a DTS of 2 seconds (and a PTS of 2.033). My reading of the RFC's Media Segments section,
A Transport Stream or audio elementary stream segment MUST be the
continuation of the encoded media at the end of the segment with the
previous sequence number, where values in a continuous series, such
as timestamps and Continuity Counters, continue uninterrupted -
unless the media segment was the first ever to appear in the Playlist
file or has an EXT-X-DISCONTINUITY tag applied to it.
seems to suggest that this is not ideal.

As for dealing with the real world where things don't always match specifications, I have been meaning to implement a continuity filter for timestamps to hide those kinds of discontinuities. This is a bit tricky since one really want to know what the next timestamp should be so that one can both know when a discontinuity has occurred and how to compensate for it. Making a few simplifying assumption can make this a great deal easier (e.g., "a jump of more than one second is a discontinuity," and "the packet durations stay the same for a given stream"), but would cause trouble where those assumptions are not true. A more general solution would need to compute the actual packet durations, which is doable without too much CPU overhead at least for the audio streams (perhaps with some heuristics to do so only when faced with a suspiciously large PTS or DTS jump). I don't think it a good idea to add something like that without a great deal of testing, but perhaps a simple filter might be added without too much effort as long as it is only used if explicitly enabled.
Feb 27, 2014 at 10:43 AM
Now it is working well ,Thanks

I want to set mediaElement read specific fragments what i hope
For example ```

EXTM3U

EXT-X-MEDIA-SEQUENCE:18197873

EXT-X-TARGETDURATION:5

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393500965000,1393500970000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393500970000,1393500975000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393500975000,1393500980000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393500980000,1393500985000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393500985000,1393500990000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393500990000,1393500995000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393500995000,1393501000000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393501000000,1393501005000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393501005000,1393501010000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393501010000,1393501015000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393501015000,1393501020000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393501020000,1393501025000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393501025000,1393501030000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393501030000,1393501035000

EXTINF:5,

/channels/zbk/yyzl/ts:sd/1393501035000,1393501040000

``` In the process of video playback, I want to set the mediaElement seek to the Fifth fragments '/channels/zbk/yyzl/ts:sd/1393500985000,1393500990000'
can you provide me an idea of ​​that?
Coordinator
Feb 27, 2014 at 2:47 PM
henric wrote:
You may want to set MediaStreamFascade.ContentType to ContentTypes.TransportStream anyway if you know that a URL is an M3U8 playlist but doesn't have a URL with a ".m3u8" extension. That will save an extra HTTP HEAD (or if the HEAD fails, a HEAD followed by a GET) on the network when starting playback.
Errr... that should be "ContentTypes.M3U8", not "ContentTypes.TransportStream." Otherwise, it would try to treat the playlist itself as a .TS stream.
Coordinator
Feb 27, 2014 at 4:15 PM
mugenkof wrote:
Now it is working well ,Thanks
Good.
I want to set mediaElement read specific fragments what i hope
[...]
In the process of video playback, I want to set the mediaElement seek to the Fifth fragments '/channels/zbk/yyzl/ts:sd/1393500985000,1393500990000'
can you provide me an idea of ​​that?
Are you trying to seek within the available segments during playback of a dynamic (live) stream or are you just trying to change which segment it start with when it start playing? I'm not sure how to accomplish the former (I suspect if you call the TsMediaManager's SeekMediaAsync() directly the stream would change, but I don't know how the MediaElement would react); the latter would currently require changes to the code in PlaylistSegmentManager.SetDynamicStartIndex().

If you really just want to play a single .TS segment, then set the source to that .TS segment's URL and make sure that IMediaStreamFascade.ContentType is either null (which is the default) or ContentTypes.TransportStream.
Feb 28, 2014 at 2:17 AM
The stream is no live. I see the work's change improves mediaelement' seek, But still is that problem.Timestamp Filtering .
I just want to find another way to solve the problem of the time stamp, The time stamp cause not use fast forward and seek time.
Coordinator
Mar 1, 2014 at 8:32 PM
I'm a bit behind on where I was expecting to be, but I am nearing another build. I have some changes to how BufferingManager and StreamBuffer interact that are nearly ready to push, and after that I only have one more thing left on my list, namely: TsTimestamp. My primary concern with the timestamp handling is to clean up how TsTimestamp interacts with StreamBuffer and TsPesPacket, but if I see a way of also filtering out discontinuities without ripping up too much other code, then I may have something next week that addresses work item 22. I believe that one of the changes I made to StreamBuffer should make dealing with timestamp discontinuities much simpler, but I have not yet had a chance to look at it.
Coordinator
Mar 3, 2014 at 6:02 PM
I have some changes that resync the timestamps, but I have broken some other things related to seeks and EOF handling. Those problems are hopefully not in the changes I pushed to CodePlex this weekend. In either case, it shouldn't take me more than a day or two to get things sorted and pushed to CodePlex.

I haven't done any extensive testing, but the stream you asked about (http://222.73.28.112/player/index_live_ios2_child.meta?channel_id=78&bit_rate=450) did play for a couple of minutes when I tried it on a WP7 device.
Mar 4, 2014 at 2:33 AM
Oh I test some minutes .
"#EXT-X-DISCONTINUITY" can't play ;
When the media play to the next "#EXT-X-DISCONTINUITY" will only sound well but the video screen will stay in the last frame of the previous paragraph.

But It can use follow " _mediaStreamFascade.SeekTarget = position;" code To continue playing well;
Coordinator
Mar 4, 2014 at 1:09 PM
There appears to be another quirk in the http://222.73.28.112/player/index_live_ios2_child.meta?channel_id=78&bit_rate=450 stream that will cause playback trouble. Sometimes it has segments that have a duration of zero. The code that decided if a playlist is dynamic finds an entry with what it considers an invalid duration and then decided that the playlist is not dynamic, just as if an #EXT-X-ENDLIST had been found. The default implementation looks like this (from SM.Media.Playlists.PlaylistDefaults),
        /// <summary>
        ///     A playlist is dynamic if it does not have an #EXT-X-ENDLIST tag and every segment has an #EXTINF with a valid
        ///     duration.
        /// </summary>
        /// <param name="parser"></param>
        /// <returns></returns>
        public static bool IsDynamicPlayist(M3U8Parser parser)
        {
            if (null != parser.GlobalTags.Tag(M3U8Tags.ExtXEndList))
                return false;

            var validDuration = parser.Playlist.All(
                p =>
                {
                    var extInf = M3U8Tags.ExtXInf.Find(p.Tags);

                    return null != extInf && extInf.Duration > 0;
                });

            return validDuration;
        }
and the actual function used can be configured at runtime with,
   PlaylistSettings.Parameters.IsDyanmicPlaylist = '<put some delegate  here>';
I'm inclined to change the compare in the default implementation for the duration from a ">" to a ">=", but I think I should probably also change the PlaylistSegmentManager code as well so that it is less picky about dynamic playlists once it has determined that a playlist is dynamic (i.e., IsDynamicPlaylist() would only called once, then the code would insist on seeing an #EXT-X-ENDLIST before stopping).

As for dealing with #EXT-X-DISCONTINUITY tags...

Doing this "properly" requires tearing up more than I'm willing to do right now. You might try looking at the playlist in your own code (I think you can get a hold of the cached copy the code already has in memory), figuring out what the offset is of the discontinuitites, then doing a MediaElement.Stop() when that offset is reached, set MediaElement.Position to that offset, then call MediaElment.Play(). That is just an idea and I haven't tried any of it...

Another approach might be to change the code that reads the playlists from the server so that it breaks the real playlist into sections without #EXT-X-DISCONTINUITY tags, and feeds those playlists to the system one at a time (switching to the next playlist when the MediaEnded event is raised. That would break seeks between sections (at least, without some work; perhaps one can treat them as chapters?).

After getting out a build to (finally) replace phonesm-20130921, dealing with this #EXT-X-DISCONTINUTITY problem (and the related problem of a segment with missing data--or, for that matter, of a missing segment, leading to pretty much the same problem) is the first thing on my list.
Coordinator
Mar 4, 2014 at 4:08 PM
I've pushed a change to the duration check, but I have not played your sample stream long enough to be sure that it is enough to keep it playing.
Mar 5, 2014 at 1:14 AM
No It also stay in the last frame of the previous paragraph.
Coordinator
Mar 5, 2014 at 9:55 PM
mugenkof wrote:
No It also stay in the last frame of the previous paragraph.
Do you mean the http://222.73.28.112/player/index_live_ios2_child.meta?channel_id=78&bit_rate=450 stream or one of the ones with #EXT-X-DISCONTINUTITY tags?
Mar 6, 2014 at 2:20 AM
Not long ago I sent you a letter.That has two urls with #EXT-X-DISCONTINUTITY tags.
The two urls "http://v.youku.com/player/getRealM3U8/vid/XNjgxMzE5NjE2/type/mp4/v.m3u8" ,
"http://v.youku.com/player/getRealM3U8/vid/XNjgxMzE5NjE2/type/hd2/v.m3u8"
Coordinator
Mar 7, 2014 at 12:45 AM
mugenkof wrote:
Not long ago I sent you a letter.That has two urls with #EXT-X-DISCONTINUTITY tags.
Right, yes I got those, I just wasn't clear if your message was regarding those streams or regarding the one you mentioned earlier. The change I had checked in would help with the earlier one, but I did not have high hopes for it to help with the #EXT-X-DISCONTINUTITY ones. I did finally manage to put together another build, and after some testing and perhaps a bugfix or two, I expect to have a beta build out this month. After that, I should hopefully have time for some new development, including addressing the #EXT-X-DISCONTINUTITY thing properly.
Mar 22, 2014 at 5:21 AM
Hi Henric
I bother you again,If I wanted to record video and save it to Isolated Storage while playing
Can you give a hint or suggestion it
Coordinator
Mar 24, 2014 at 2:30 AM
Now that I've finally posted a new downloadable build to replace phonesm-20130921, I've gone back to making more drastic code changes. One of the things I'm doing right now is to add an abstraction layer to hide HttpClient I had thought that it would be sensible to use something MS provided for all the platforms phonesm supports, but it turns out that with the cache problems (one can't bypass it in all cases and it can chew up temporary storage on the phone), the out of memory exceptions, and various other platform quirks, I want to able to more easily plug in other things. I'm planning on adding a alternate implementation based on the C++ REST SDK (assuming MS doesn't beat me to it). This should also make it much easier to plug in an implementation that supports reading from isolated storage.

To capture data from HLS streams, for a recorded program, you could use M3U8Parser to load the playlist into memory and then iterate over the segments (M3U8Parser.Playlist) to download everything you find there. If you want to grab a live stream, you would probably want to create an instance of PlaylistSegmentManager, and then use PlaylistSegmentManager.Playlist to iterate over all the segments. If you want to get fancier, you should be able to take the demuxed audio and video packets that are headed to MediaElement and write them to a new container. Unless the phone's Media Foundation code can be persuaded to mux them into .mp4 files then this might involve quite a bit of code. I suppose you might compile ffmpeg for the phone and use it to convert the raw .ts segments into an .mp4 file. If you do create an .mp4 file, then you don't need phonesm for playback.
Mar 24, 2014 at 6:45 AM
Yeah, Thanks for your idea. I will try it
Hope the project getting better. Hope in the future to solve problems with #EXT-X-DISCONTINUTITY tags.
Coordinator
Mar 24, 2014 at 8:31 AM
Good luck. Let me know how it goes.

I should have the HttpClient --> IWebReader changes pushed to CodePlex in the next day or so. When that is done, the next item on my agenda is to look at how to deal with stream discontinuities (including those caused by #EXT-X-DISCONTINUITY). I'm not yet sure if it will require days or weeks worth of work to solve...
Apr 9, 2014 at 5:05 AM
I sent you a message yet , Can You received?
the latest project cause a new problem, some m3u8 files is not readed right.
in the previous project I can set the contentype to m3u8 can readed. But the latest project can't read right
Coordinator
Apr 9, 2014 at 5:43 AM
I sent a reply about four hours after your email arrived:
When I try playing that M3U8, I sometimes get some segment
data, but it will usually cut me off before I get a whole
segment and then give me a "403 Forbidden". The retry code
did have some problems that I fixed (I think I caused them
after the phonesm-1.2.2 tag), but it doesn't really get
things playing. I pushed those changes and a few other
minor things that were in my local tree to CodePlex. It
might help you play that stream; it might not.

If you still can't play the stream, try to get me a .saz
trace from Fiddler2 and a copy of the log from VisualStudo's
"Output" window when playing the stream with a debug build.
Apr 9, 2014 at 7:02 AM
I sent a email for you with four files