4 Replies
      Latest reply on Feb 20, 2020 2:26 PM by keepsimple
      keepsimple Level 1 Level 1 (0 points)

        Hi,

         

        I'm using AVPlayer and AVAssetResourceLoaderDelegate to handle a custom video playback (streaming) from remote server.  In the delegate code, it will uses its own NSURLSession to create a data task retrieving the video from the remote server, and feed the data to AVAssetResourceLoader.

         

        The first loadingRequest I got is good:  it's a contentInformationRequest and I do the following:  (cotentType will be "video/mp4")

         

            request.contentInformationRequest.byteRangeAccessSupported = true;
            request.contentInformationRequest.contentType = response.MIMEType;
            request.contentInformationRequest.contentLength = totalLength;

         

        after that I'll get the first data request, however the data request always has "requestsAllDataToEndOfResource" set to true, and requestedLength set to "totalLength",  as in this debug output:

         

        data request = requested offset = 0, 
        requested length = 28875525, 
        requests all data to end of resource = YES, 
        current offset = 0>

         

        I was expecting this data request is only asking for a range of data, especially it's the first data request (after the contentInfoRequest). Why is that?

         

        Then my code would continue to handle this as it's getting more data from the remote server asynchronically, it will give it to the data request:

         

        - (void)URLSession:(NSURLSession *)session
                  dataTask:(NSURLSessionDataTask *)dataTask
            didReceiveData:(NSData *)data
        {
        
                    [self.currentRequest.dataRequest respondWithData:respondData];

         

        However, after the above callback responds to the dataRequest with data for a few time (3 or 4 times), we hit the 2nd issue, the loadingRequest was cancelled:

         

        data request = 
        requested offset = 0, 
        requested length = 28875525, 
        requests all data to end of resource = YES, 
        current offset = 25284>
        
        

        We can see that the request currentOffset is moving forward but far from finished.  What could trigger the cancel?  (The user did not cancel it via AVPlayer UI).

         

        So,  we have 2 questions:

        1).  why the first data request always asks for the whole length of data?

        2).  what could trigger cancelling the loadingRequest when we are feeding the data to the data request?

         

        Thanks.

        • Re: AVAssetResourceLoadingRequest dataRequest issue
          mildm8nnered Level 1 Level 1 (0 points)

          It's been a while since I worked with this API, but I think what might be happening is that the AVPlayer is trying an optimistic request first ("give me all the data"), and then when it sees what the response rate is (how quickly you callback, and with how much data), it's then cancelling the request for everything, and is going to make some more reasonable ranged requests afterwards.

           

          Do you get any further requests after the cancel?

            • Re: AVAssetResourceLoadingRequest dataRequest issue
              keepsimple Level 1 Level 1 (0 points)

              I did not get further requests after the cancel.

               

              The cancel is still confusing to me as I'm testing locally using iOS simulator and local server, which has very low latency for the response.  And it seems it was cancelled after 3 times of dataRequest respondWithData().

                • Re: AVAssetResourceLoadingRequest dataRequest issue
                  keepsimple Level 1 Level 1 (0 points)

                  I compared the sequence of requests with a regular case when AVPlayer is created with a http URL without using delegate.  I have two observations:

                   

                  1. In both cases, AVPlayer has first request asking for ContentInfo and range 0-1 (2 bytes) and 2nd request asking for the whole range (full length) of the video asset.

                   

                  2. In regular case,  AVPlayer seems to "cancel" / "stop" the 2nd request as well, after receiving some (around 100k bytes) data.

                   

                  3. In regular caes, AVPlayer will continue to send 3rd request with requested offset following the 2nd request data received. But in the problematic delegate case,  there was not 3rd request.

                   

                  So,  now the question is, why didn't the delegate get a 3rd request from AVPlayer?

                    • Re: AVAssetResourceLoadingRequest dataRequest issue
                      keepsimple Level 1 Level 1 (0 points)

                      I found the problem.  The reason is that AVPlayerItem (and AVAsset) cannot handle a URL for video if there is no known file extension, e.g. something like ".mp4".

                       

                      By observing the "status" key of AVPlayerItem,  I found the error reason is "This media format is not supported" even though I have already set the content-type as "video/mp4" in ContentInformationRequest.

                       

                      Anyway, after manually adding ".mp4" in the URL, I was able to get additional loading requests after the 2nd request was cancelled. And the video playback works now .

                       

                      Btw, this bug / behavior was reported on 2012, but it seems still not fixed.  http://openradar.appspot.com/radar?id=1516408