Page 1 of 1

[CDS API] - Support Range requests/seeking

PostPosted: Sun Aug 26, 2012 10:44 am
by will
Specifically, implement it in the same way/use the same implementation that is used for content servered via DLNA to give a consistant playback experience for users.

Based on limited testing, there seems to be partial support when giving specific ranges e.g. bytes=X-Y, but not when making open ended requests e.g. bytes=X-

This causes quite a few problems on Android using ServiiGo:
*Seeking doesn't work, and users don't understand why when it works using DLNA
*Seeking doesn't work, which means that if you pause a video, read an email etc and come back, the video playler may end up starting from the begining again because it cannot start where it left off
*MX Player (plus some others that i've tested), get stuck trying to detect if they can use H/W decoding. This causes quite a large delay when loading the video depending on the device and video container/codec. Looking at the logs, they make multiple failed requests using range headers. This seems to be part of the core android media framework, stagefright.

I would love for this to be in 1.1 :-)

https://bitbucket.org/xnejp03/serviio/i ... ts-seeking


In the future I want to be able to download videos for offline viewing, filling in the ETag field with a hash of the transcoded video and creation date would allow me to start where I left off in the case of the connection dropping.

Re: [CDS API] - Support Range requests/seeking

PostPosted: Fri Sep 07, 2012 7:29 pm
by will
A few more thoughts for this that I've had recently, looking around this appears to be a fairly common way to implement resumed downloads which I think is very important for mobile devices which often switch between networks/loose signal when out and about.

From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
14.27 If-Range

If a client has a partial copy of an entity in its cache, and wishes to have an up-to-date copy of the entire entity in its cache, it could use the Range request-header with a conditional GET (using either or both of If-Unmodified-Since and If-Match.) However, if the condition fails because the entity has been modified, the client would then have to make a second request to obtain the entire current entity-body.

The If-Range header allows a client to "short-circuit" the second request. Informally, its meaning is `if the entity is unchanged, send me the part(s) that I am missing; otherwise, send me the entire new entity'.

If-Range = "If-Range" ":" ( entity-tag | HTTP-date )

If the client has no entity tag for an entity, but does have a Last- Modified date, it MAY use that date in an If-Range header. (The server can distinguish between a valid HTTP-date and any form of entity-tag by examining no more than two characters.) The If-Range header SHOULD only be used together with a Range header, and MUST be ignored if the request does not include a Range header, or if the server does not support the sub-range operation.

If the entity tag given in the If-Range header matches the current entity tag for the entity, then the server SHOULD provide the specified sub-range of the entity using a 206 (Partial content) response. If the entity tag does not match, then the server SHOULD return the entire entity using a 200 (OK) response.


Example 1: Client does not have a partially downloaded file
  Code:
*Client makes a normal request to the server

*Server replies with the whole file using a 200 response


Example 2: Client has a partially downloaded file, that is natively delivered (but the client does not need to know that)
  Code:
*Client makes a request with the following header info
**Range:Bytes=sizeOfExistingPartialFile-
**If-Range:partialFileDate

*Server checks date against the date the file was last updated in the database,
*If the supplied date is more recent, server replies with the requested range using a 206 (Partial content) response
*else, the server replies with the whole file using a 200 response


Example 3: Client has a partially downloaded file, that is transcoded (but the client does not need to know that)
  Code:
*Client makes a request with the following header info
**Range:Bytes=sizeOfExistingPartialFile-
**If-Range:partialFileDate

*Server first checks for an existing transcoding job, if there isn't one then the server replies with the whole file using a 200 response
*If there is an existing transcoding job, the server checks to see if it was started before the supplied date, if so it returns the requested range using a 206 (Partial content) response
*else, the server returns the whole file using a 200 response


So in summary, if client wants to download part of a file, and wants to ensure that that part matches its existing part, then it sends the date that it created the first part. The server then checks the date and responds accordingly. This then means that the client does not need to keep track of anything, and the server just needs to track the date/time a file is updated in the database, or the date/time that a transcoding job was started.

Re: [CDS API] - Support Range requests/seeking

PostPosted: Sun Sep 09, 2012 9:12 pm
by zip
I will also have to make sure it works with Flowplayer, which would not support this. They either support range header or a specific URL parameter (e.g. &start=200) meaning number of seconds to skip.

Might have to implement more ways.

Re: [CDS API] - Support Range requests/seeking

PostPosted: Sun Sep 09, 2012 9:38 pm
by will
Yes seconds to skip would probably work best with flow player.

From what I understand If-Range is used with a Range header to get the server to specially check if you have the same file, and is only needed for resuming partial downloads. For video players a standard Range header is all that is needed for seeking, and is what the Android media library tries first even for playing from the beginning for a few times (which is stupid as it is clear from the first request that Range headers aren't supported), before giving up and doing a normal request.