使用AVAssetResourceLoader时视频流失败

时间:2016-10-10 16:37:54

标签: ios swift video streaming

我们在Swift IOS应用程序中使用视频流,效果非常好。问题是我们想使用AVAssetResourceLoader,所以我们可以使用我们自己的URLSession而不是AVPlayer使用的任何内容向流服务器发出请求(我完全无法找出AVPlayer使用的会话或如何影响它使用的会话。)

确切的行为是,对.m3u8文件上的两个字节调用shouldWaitForLoadingOfRequestedResource,然后再次调用它请求整个文件,然后(根据开始时间)请求正确的.ts文件。在我们获取.ts文件后,视频播放器根本无法做任何事情。

无论我们是否使用示例流式视频文件" https://tungsten.aaplimg.com/VOD/bipbop_adv_example_v2/master.m3u8"或我们自己的服务器。如果我们不使用AVAssetResourceLoader(我们可以从我们的服务器告诉),直到请求.ts文件,序列是相同的。此时,当我们不使用自定义加载程序时,AvPlayer会显示视频并不断请求.ts文件。如果我们注释掉与AVPlayer的所有其他交互,包括设置行为相同的初始时间,那么我只会包含来自viewDidLoad和shouldWaitForLoadingOfRequestedResource的代码。

如果我们只是删除" xyzzy"前缀使AVAssetResourceLoader不被使用,一切正常。此外,我想重要的是,如果我们定位的视频文件不是流媒体文件,那么一切都有效。

我们为.ts文件转换mime类型的另一件事产生了某种奇怪的动态uti,但这似乎与问题无关,因为即使我们对uti进行硬编码也是如此事情发生了。

override func viewDidLoad() {
        super.viewDidLoad()
        avPlayer = AVPlayer()
        avPlayerLayer = AVPlayerLayer(player: avPlayer)
        videoView.layer.insertSublayer(avPlayerLayer, at: 0)
        videoView.backgroundColor = UIColor.black         
        url = URL(string: "xyzzy" +  currentPatient.videoURL())!
        let asset = AVURLAsset(url: url)
        asset.resourceLoader.setDelegate(self, queue: DispatchQueue.main)
        let item = AVPlayerItem(asset: asset)

        let avPlayerItem = item
        avPlayer.replaceCurrentItem(with: avPlayerItem)

        videoScrollView.delegate = self
        videoScrollView.minimumZoomScale = 1.0
        videoScrollView.maximumZoomScale = 6.0




    }

 func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
        let urlString = loadingRequest.request.url?.absoluteString
        let urlComponents = urlString?.components(separatedBy: "xyzzy")
        let url = URL(string: urlComponents![1])           
        let request = loadingRequest.dataRequest!         
        let infoRequest = loadingRequest.contentInformationRequest

        let task = globalSession.dataTask(with: url!) { (data, response, error) in
            self.avPlayerThread.async {
                if error == nil && data != nil {

                    let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, response?.mimeType as! CFString, nil)

                    if let infoRequest = infoRequest {
                        infoRequest.contentType = uti?.takeRetainedValue() as? String
                        if request.requestsAllDataToEndOfResource == false {
                            infoRequest.contentLength = Int64(request.requestedLength)
                        } else {
                            infoRequest.contentLength = Int64((data?.count)!)
                        }


                        infoRequest.isByteRangeAccessSupported = true


                    }


                    if infoRequest == nil  || request.requestsAllDataToEndOfResource == true {

                            loadingRequest.dataRequest?.respond(with: data!)                          
                    }

                    loadingRequest.finishLoading()
                } else {
                    print ("error \(error)")
                    loadingRequest.finishLoading(with: error)
                }

            }
        }
        task.resume()

        return true

    }

0 个答案:

没有答案