2016-12-22 48 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顯示它,你」將能夠在畫布上繪製而不受限制。

相關問題