2016-12-22 20 views
0

从Firefox 49开始,IP摄像机的MJPEG流使用内部服务冻结第一帧。这在Chrome中不会发生。我找不到可能导致此错误的FF 49更改日志中的任何更改。请记住,这段代码不是我的,并且非常古老,但它仍然可以在Chrome中正常工作。代码 件我认为可能会导致错误:自从Firefox 49开始,MJPEG流在第一帧冻结49

CameraplayerUI.js 
self.drawStream = function (image) { 
      //#region Argument validation and sanitization 

      if (typeof image === "undefined" || image === null) { return false; } 
      if (typeof image.src === "undefined" || image.src === null) { return false; } 
      if (!image.complete) { return false; } 

      if (_stream.width !== image.width) { _stream.width = image.width; } 

      if (_stream.height !== image.height) { _stream.height = image.height; } 

      //#region Argument validation and sanitization 

      if(_isLive !== true){ 
       _isLive = true; 
       $(_image).hide(); 
       $(_stream).show(); 
      } 

      _ctx.drawImage(image, 0, 0, _stream.width, _stream.height); 
      self.source = image.src; 
      return true; 

/** Mjpegstream.js 
     * Updates the current stream based on the elapsed time since last update. 
     * Warning: Numeric representations for all parameters are used without validation for 
     *   performance considerations. 
     * 
     * @param {Integer} time  - Current time} 
     * @param {Integer} elapsedTime - Elapsed time since last update cycle. 
     */ 
     this.update = function (time, elapsedTime) { 
      if (!self.isOpen) { return false; } 

      //#region Argument validation and sanitization 

      time = +time; // Unary plus operation. Numeric representation. 
      elapsedTime = +elapsedTime; // Unary plus operation. Numeric representation. 

      //#endregion Argument validation and sanitization 

      _serviceReauthenticationTimer = _serviceReauthenticationTimer - elapsedTime; 
      if (_serviceReauthenticationTimer <= 0) { 
       downloadAsync(_userId, _userKey, this.cameraId, update_callback); 
      } 

      // Firefox MJPEG stream fix. 
      if (navigator.userAgent.toLowerCase().indexOf("firefox") > -1) { 
       if (this.data !== "undefined" && this.data !== null) { 

        self.data.src = _stream.src; 

       } 
      } 

      return true; 
     }; 

Cameraplayer.js 
if (self.isLive) { 
       _time = now; 
       ui.setTime(_time); 

       if (!_mjpegStream.isAuthenticated) { 
        ui.showAuthenticationNotification(false, _mjpegStream.error); 
        self.hasError = true; 
       } else if (_mjpegStream.error !== null) { 
        ui.showError(true, _mjpegStream.error); 
        self.hasError = true; 
       } else if (_mjpegStream.isOpen) { 
        ui.clearNotifications(); 
        if (_mjpegStream.isPlaying) { 
         if (_mjpegStream.update(_time, elapsedTime)) { 
          ui.drawStream(_mjpegStream.data); 
         } 
        } else { 
         _mjpegStream.play(); 
        } 
       } else if (_mjpegStream.isConnecting) { 
        ui.showLoading(true); 
        return false; 
       } else { 
        ui.showLoading(true); 
        _mjpegStream.open(_request); 
        return false; 
       } 
      } else { 
       _time = time; 

记住这个节目是巨大的,我只是把我认为可能会导致错误的片段。它适用于49之前的所有Firefox版本,当前在Chrome上。

回答

0

您正在依靠chrome bug

根据specs

... when a CanvasImageSource object represents an animated image in an HTMLOrSVGImageElement, the user agent must use the default image of the animation (the one that the format defines is to be used when animation is not supported or is disabled), or, if there is no such image, the first frame of the animation, when rendering the image for CanvasRenderingContext2D APIs.

MJPEG流是这些动画图像的一部分,因此UAS必须只返回第一帧。铬最近遵循这部分规格,但只有为GIF图像。

因此,仍然有强制MJPEG流完全重新加载的解决方法,在每次重新绘制的请求中添加一个随机参数,但是您将失去MJPEG格式的所有优点并发出大量繁重的请求。

var url = 'http://webcam.st-malo.com/axis-cgi/mjpg/video.cgi?resolution=352x288'; 
 

 
var img = new Image(); 
 
img.onload = drawAndReload; 
 
// check if there are already parameters in the passed url 
 
var paramHead = url.indexOf('?') > 0 ? '&' : '?'; 
 
img.src = url; 
 
var ctx = c.getContext('2d'); 
 

 
function drawAndReload(){ 
 
    if(c.width !== this.naturalWidth){ 
 
    c.width = this.naturalWidth; 
 
    c.height = this.naturalHeight; 
 
    } 
 
    ctx.drawImage(this, 0, 0); 
 
    // reset the image 
 
    this.src = ''; // should not be necessary 
 
    this.src = url + paramHead + Math.random(); // force no-cache 
 
    }
<canvas id="c"></canvas>

一个真正的解决办法是你的MJPEG流转换为视频流服务器端,然后使用MediaSource API来获取块,并在HTMLVideoElement显示它,你”将能够在画布上绘制而不受限制。

相关问题