简体   繁体   中英

Swift Mjpeg Streaming Only Showing Single Frame

I am trying to create a Mjepg stream. I have followed a tutorial and it's not a lot of code to get a stream to lead but I don't understand why it's not working for me.

//Class properties

private var mjpegSession : URLSession?
private var mjpegData:Data = Data()

override func viewDidLoad(){
...
mjpegSession =  URLSession(configuration: .default, delegate: self, delegateQueue: nil)
        if let url = URL(string: "http://cam6284208.miemasu.net/nphMotionJpeg?Resolution=640x480") {
           mjpegSession?.dataTask(with: url).resume()
        }
}

extension ViewController: URLSessionDataDelegate, URLSessionTaskDelegate {
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        mjpegData.append(data)
    }

    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
           if mjpegData.count > 0 {
                DispatchQueue.main.async{
                    if let image = UIImage(data: self.mjpegData){
                        self.cameraImageView.image = image
                    }
                }
            }
            mjpegData.removeAll()
            

        completionHandler(.allow)
    }
 }

The tutorial removed all the data in on the line that says mjpegData.removeAll()

However if I do that the image is incomplete and there's errors in the log about not being able to decode an image. If I remove it, I get a complete frame or image but I only get one. Using that url in VLC shows a constant stream so I know the url is valid stream. Thanks for everyone's time.

So I found a solution having to do with queues and background threads that seemed to fix my problem. Here's the solution in case anyone else runs into this.

//Class properties

private var mjpegSession : URLSession?
private var mjpegData:Data = Data()

override func viewDidLoad(){
...
self.queue = DispatchQueue(label: "MjpegQueue")
        self.mjpegSession =  URLSession(configuration: .default, delegate: self, delegateQueue: nil)
        if let url = URL(string: "http://cam6284208.miemasu.net/nphMotionJpeg?Resolution=640x480") {
           DispatchQueue.global().async {
                self.mjpegSession?.dataTask(with: url).resume()
            }
        }
}

extension ViewController: URLSessionDataDelegate, URLSessionTaskDelegate {
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        mjpegData.append(data)
    }

    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
                   queue.sync{
            if mjpegData.count > 0 {
                
                let data = self.mjpegData
                if let image = UIImage(data: data){
                    DispatchQueue.main.async {
                        self.cameraImageView.image = image
                    }
                }
            }
            
            mjpegData.removeAll()
        }
        
        
        
        completionHandler(.allow)
    }
 }
import UIKit

class   ViewController
:       UIViewController, URLSessionDataDelegate
{
    //  Variables
    @IBOutlet weak var  imageview   : UIImageView!
    private var         queue       = Data( )

    //  View : Did Load
    override func   viewDidLoad( )
    {
        super.viewDidLoad()

        let session = URLSession( configuration: .default, delegate: self, delegateQueue: nil )
        if let url  = URL( string: "http://cam6284208.miemasu.net/nphMotionJpeg?Resolution=640x480" )
        {
            session.dataTask( with: url ).resume( )
        }
    }

    //  URLSession : Data Callback
    func    urlSession
    (
        _ session           : URLSession,
        dataTask            : URLSessionDataTask,
        didReceive data     : Data
    )
    {
        queue.append( data )
    }

    //  URLSession : Response Callback
    func    urlSession
    (
        _ session           : URLSession,
        dataTask            : URLSessionDataTask,
        didReceive response : URLResponse,
        completionHandler   : @escaping( URLSession.ResponseDisposition ) -> Void
    )
    {
        if  queue.count > 0
        {
            if let  image = UIImage( data: queue )
            {
                DispatchQueue.main.async
                {
                    self.imageview.image    = image
                }
            }
        }
        queue.removeAll( )
        completionHandler( .allow )
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM