Skip to content

A small framework to play mjpeg streaming videos within iOS applications

Notifications You must be signed in to change notification settings

calvinchengx/MjpegStreamingKit

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 

Repository files navigation

MjpegStreamingKit

MjpegStreamingKit is a small iOS framework providing a view controller for UIImageView to play mjpeg video streams with content type multipart/x-mixed-replace within it.

How to use

Using this controller is quite simple... all you have to do is to import the framework, initialize it with an UIImageView and call the play() method:

import MjpegStreamingKit

let imageView = UIImageView(frame: rect)
let streamingController = MjpegStreamingController(imageView: imageView)
// To play url do:
let url = NSURL(string: "http://mjpeg.streaming.url/movie.mjpeg")
streamingController.play(url: url!)

// As an alternative you could do as well:
let imageView = UIImageView(frame: rect)
let streamingController = MjpegStreamingController(imageView: imageView)
streamingController.contentURL = NSURL(string: "http://mjpeg.streaming.url/movie.mjpeg")
streamingController.play() // if contentURL is not nul it will be played

// Or directly init the controller with both the imageView and the url
let imageView = UIImageView(frame: rect)
let url = NSURL(string: "http://mjpeg.streaming.url/movie.mjpeg")
let streamingController = MjpegStreamingController(imageView: imageView, contentURL: url!)
streamingController.play()

There is a slight difference between play(url: NSURL) and play():

  • play(url: NSURL): when called if another video is playing it will be stopped and the new source will start
  • play(): when called if another video is playing nothing will happen, otherwise it will start reproducing the contentURL

To stop a video all you need to do is to call the stop() method:

streamingController.stop() // this will stop the video and the data transfer

Initialize with Interface Builder

You can of course create the UIImageView with interface builder (an IBOutlet) and initialize the MjpegStreamingController with it.

Performing actions during the loading time

MjpegStreamingController has two properties that can be set to perform actions at the beginning and at the end of the loading time:

  • var didStartLoading: (()->Void)?: this closure is called right after the play() method has been invoked and should be used to set-up whatever should happen while the stream is loading (like displaying an activity indicator and start its animation)
  • var didFinishLoading: (()->Void)?: this closure is called right before displaying the first frame of the video stream and should be use to undo what was done by didStartLoading (like stopping the anipation of the activity indicator and hide it)
class ViewController: UIViewController {
  @IBOutlet weak var imageView: UIImageView!
  @IBOutlet weak var loadingIndicator: UIActivityIndicatorView!
  
  var streamingController: MjpegStreamingController!
    
  override func viewDidLoad() {
    super.viewDidLoad()
    streamingController.didStartLoading = { [unowned self] in
      self.loadingIndicator.hidden = false
      self.loadingIndicator.startAnimating()
    }
    streamingController.didFinishLoading = { [unowned self] in
      self.loadingIndicator.stopAnimating()
      self.loadingIndicator.hidden = true
    }
  }
  
  ...
}

These two properties are completely optionals hence you are free to ignore them

Authentication

If when attempting to connect MjpegStreamingController receive an authentication challenge it will try to handle it in different ways depending on the authentication type and if the authenticationHandler is set:

  • authentication type is NSURLAuthenticationMethodServerTrust: usually happening if the url is using https instead of http, this case is automatically handled and no action is required
  • any other authentication type: in this case it checks if the closure authenticationHandler is set:
    • if it's set then it calls it passing in input the authentication challange, it will be then up to the closure to provide the NSURLSessionAuthChallengeDisposition and NSURLCredential to continue with the authentication process
    • if it's not set MjpegStreamingController will fallback on the default behaviour of a NSURLSession in case of authentication challenges

Here it is an example of how to implement a custom authentication handler:

streamingController.authenticationHandler = { challenge in
  // Checking if credentials are available in key chain
  if let credentials = NSURLCredentialStorage.sharedCredentialStorage().credentialsForProtectionSpace(challenge.protectionSpace) where credentials.count > 0 {
    return (.UseCredential, credentials.values.first)
  } else { // if not already available generate a credentials object to use
    let credentials:  NSURLCredential? = self.retrieveCredentials() // a method that is creating NSURLCredential object
    return (.UseCredential, credentials)
  } 
}

A simple way to deal with HTTP Basic Auth without having to provide an authentication handler is to put the credentials directly inside the url as follow:

streamingController.contentURL = NSURL(string: "http://username:[email protected]/movie.mjpeg")

About

A small framework to play mjpeg streaming videos within iOS applications

Resources

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Swift 87.5%
  • Objective-C 12.5%