首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >自Firefox 49以来,MJPEG流在第一帧冻结

自Firefox 49以来,MJPEG流在第一帧冻结
EN

Stack Overflow用户
提问于 2016-12-23 05:03:00
回答 1查看 571关注 0票数 0

从Firefox 49和更高版本开始,来自IP摄像头的MJPEG流会使用内部服务在第一帧冻结。这在Chrome中不会发生。我在FF 49更改日志中找不到任何可能导致此错误的更改。请记住,这段代码不是我写的,而且非常旧,但它在Chrome上仍然可以很好地工作。我认为可能会导致错误的代码片段:

代码语言:javascript
复制
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上

EN

回答 1

Stack Overflow用户

发布于 2016-12-25 13:30:23

您依赖于chrome bug

根据specs的说法:

...当CanvasImageSource对象表示HTMLOrSVGImageElement中的动画图像时,在为CanvasRenderingContext2D API呈现图像时,用户代理必须使用动画的默认图像(格式定义的图像将在动画不受支持或禁用时使用),或者,如果没有此类图像,则使用动画的第一帧。

MJPEG流是这些动画图像的一部分,因此UAs必须仅返回第一帧。Chrome最近遵循了这部分规范,但只对GIF图像使用

因此,仍然可以通过在每次重绘时在请求中添加一个随机参数来强制完全重新加载MJPEG流,但您会失去MJPEG格式的所有优点,并发出许多繁重的请求。

代码语言:javascript
复制
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
  }
代码语言:javascript
复制
<canvas id="c"></canvas>

一个真正的解决方案是将您的MJPEG流转换为服务器端的视频流,然后使用MediaSource API获取块并将其显示在HTMLVideoElement中,这样您就可以不受限制地在画布上绘制。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41291610

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档