404 errors - try to continue to read

Oct 28, 2014 at 2:35 PM

When I try to play this stream : http://se-1.se.beinsport1-hls.live.numericable.tv/live/hls/beinsport1/ipadstream800beinsport1.m3u8, there is often some 404 errors on some segments, so it stops to play.

If I play it with VLC, visually, I don't see any problem.

Is there a way to ignore some segments and to continue to play even there is some errors ?
Oct 29, 2014 at 7:35 AM
Could you try changing the,
            var duration = TimeSpan.FromSeconds(60);
in SM.Media.Hls' HlsPlaylistSegmentManager.SetDynamicStartIndex(...) from 60 seconds to 20 seconds?

Oct 29, 2014 at 11:38 AM
Edited Oct 29, 2014 at 11:42 AM
When I set the duration to 20 seconds (or 30 seconds, or 10 seconds, or 5 seconds), it doesn't change anything. Sometimes, the stream can't start due to 404 errors. Sometimes, the stream starts to play with no error but after 30 or 40 seconds of playing, I get some 404 errors and it stops.

What is strange is I don't see any problem with other HLS players (VLC or HLS Media Player from 3ivx). So, I did a little test : in GetByteArrayAsync method in WinRtHttpClientWebReader class, I retry several times if I get a 404 error. And now, it works well ! In fact, there must be a problem on the server (or with the HttpClient class). The server returns sometimes 404 error but if you retry, it works well.
Oct 29, 2014 at 7:36 PM
Yikes. I had completely forgotten about that AES-128 key read. The M3U8 classes are all synchronous, so I jammed the read in there with a bit of a hack to let it run async, and promptly forgot about it.

VLC does retries for the key as well, but it only reads the key when it starts reading the stream.

When looking at your stream, I saw a few things::

--- SM.Media.Web.HttpConnectionWebReader's GetByteArrayAsync() ignores the status code. This would not matter unless one changes the default reader. (I happened to be testing with it since I can easily hard-code a proxy that forces all the traffic through Fiddler.)

--- The key is not cached the way that it should be. phonesm tried to cache the 16-bytes worth of key data in a Dictionary<> that was (unfortunately) recreated every time the playlist was refreshed. This bug was hidden by the Silverlight HttpClient's cache; the WinRT HttpClient actually has a way of turning off the cache.

--- Nested retry handlers will do bad things (i.e., 3 retries of 3 retries is 9). There is now a pending change to the retry code to fix this by throwing a different exception when the retry count runs out. That way, the outer retry handler can know it came from another retry handler.

-- The retry policy code needs some though. Part of the problem is that it predates the change to an IoC container; part is that it currently retries gateway timeout (504), request timeout (408), and internal server error (500). It's simple enough to change the table in RetryPolicy--either at compile time or at runtime, but it needs some thought to avoid causing trouble (it's easy enough for a given stream, but there are some weird web servers out there).

-- Last, but not least, the AES-128 key reader did not do any retries at all. It may also have left unobserved Task exceptions floating around when there was a failure (which is bad).

--- Since no cancellation token was available where the key read happened, things can get stuck for as long as the HTTP stack feels like keeping it that way. No amount of mashing the stop button will speed things up.

As a minor nit, the server claims the key is UTF-8 encoded text; "application/octet-stream" would probably be better. (This did not cause any trouble with phonesm.)

Look for some changes in the next day or so. I was about to do some testing so I could push what I already had when I saw your last post an though I'd, "just take a quick look" (file that under, "famous last words").