Issue with video stream when header contains accept-ranges

0

I am trying to stream video from server with accept-ranges to allow users to change position on client-side video player (in my case jwplayer)

When accept-ranges code is included client (jwplayer or opened only in chrome directly from url) plays about 15s normally and after it is every chunk asked with new request, practically after 15s only goes through method only one time, connection is broken in or after Response.Flush() without any error (sometimes Flush() gets error code 0x800704CD or 0x800703E3 or 0x80070016 in about 10% of requests), after that is Response.IsClientConnected=false so method ends.

Client is asked for range for example 123456-empty, there is not specified end part of range.

I guess that this is not right behavior, maybe there is wrong headers on Response.. or is normal, that client video player is creating new request for every chunk? Actually it takes on my PC about 80% of CPU.

Problem is only while streaming video and when is created a lot of new requests in same time, in usual situations when file is downloaded there is no problem when is establishment of broken downloads for example.

When accept-ranges code missing, there is no problem in video streaming, all server->clients transfers are in while loop and only when user broke connection methods end.

(This solution is running under ASP.NET MVC4)

Currently used code :

    public void Method()
    {
        string path = @"filePath.mp4";
        FileInfo file = new FileInfo(path);
        long fileLength = file.Length;

        byte[] buffer = new byte[64 * 1024];
        long dataToRead = fileLength;
        long startbyte = 0;
        long location = 0;
        long readLength = 0;

        Response.AddHeader("Accept-Ranges", "bytes");
        Response.ContentType = "video/mp4";

        if (!String.IsNullOrEmpty(Request.Headers["Range"]))
        {
            string[] range = Request.Headers["Range"].Split(new char[] { '=', '-' });
            location = long.Parse(range[1]);
            if (location >= 0 && location <= fileLength)
            {
                Response.StatusCode = 206;
                Response.AddHeader("content-range", String.Format(" bytes {0}-{1}/{2}", location, fileLength - 1, fileLength));
                startbyte = location;
                dataToRead = fileLength - startbyte;
                Response.AppendHeader("content-length", dataToRead.ToString());
            }
        }
        else
        {
            Response.StatusCode = 200;
            Response.AddHeader("Content-Range", String.Format(" bytes {0}-{1}/{2}", 0, fileLength - 1, fileLength));
            Response.AppendHeader("content-length", fileLength.ToString());
        }

        try
        {
            using (Stream stream = System.IO.File.OpenRead(path))
            {
                if (startbyte > 0)
                {
                    stream.Seek(startbyte, SeekOrigin.Begin);
                }

                while (dataToRead > 0)
                {
                    if (Response.IsClientConnected)
                    {
                        readLength = stream.Read(buffer, 0, buffer.Length);

                        Response.OutputStream.Write(buffer, 0, (int)readLength);
                        Response.Flush();

                        dataToRead = dataToRead - readLength;
                    }
                    else
                    {
                        dataToRead = -1;
                    }
                }
            }
        }
        catch (EndOfStreamException endStream)
        {
            Log.Error(endStream.Message, endStream);
        }
        catch (TimeoutException timeout)
        {
            Log.Error(timeout.Message, timeout);
        }
        catch (Exception e)
        {
            Log.Error(e.Message, e);
        }
        finally
        {
            Response.End();
        }
    }
c#
asp.net-mvc
video-streaming
asked on Stack Overflow Jun 14, 2014 by Johnny • edited Jul 29, 2014 by tereško

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0