繁体   English   中英

平滑可变帧率(视频)

[英]Smooth variable frame-rate (video)

我有一个为查看IP摄像机流而编写的motion-jpeg解码器。 效果很好,我可以使用多个设备轻松达到30 fps以上。 我的问题是这些帧可能会通过网络爆发。

我想要实现的是一个公式,用于平均两帧之间的时间以获得更稳定的播放。 目前,我的框架已从网络线程放入ConcurrentQueue,最新的框架显示在UI线程上。 下面是我当前用于平滑视频流的代码,但是它不能按我的计划工作...

PlaybackFrame )持有BitmapImage->“ Image ”的类
base.getFrame() )从ConcurrentQueue中检索PlaybackFrame

    private const int MAX_FRAME_DELAY = 500;
    private const float RATE_FACTOR = 0.1f;

    private long last_frame_time;
    private long last_update_time;
    private float rate;

    //=============================


    public override bool Get(out BitmapImage image) {
            PlaybackFrame f = null;
            if (base.getFrame(out f)) {
                long now = Environment.TickCount;
                if (last_frame_time > 0) {
                    // Get # of frames in buffer
                    int count = getCount();
                    //
                    // Get duration since last update & last frame displayed
                    int update_duration = (int)(now - last_update_time);
                    int frame_duration = (int)(now - last_frame_time);
                    //
                    // estimated delay based on current frame-rate
                    float target_rate = 0;
                    if (count > 0) target_rate = update_duration / (float)count;
                    //
                    // offset actual delay/rate by current value
                    last_update_time = now;
                    rate = lerp(rate, target_rate, RATE_FACTOR);
                    //
                    // [backup] if duration exceeds 0.5 seconds, display next frame
                    if (frame_duration >= MAX_FRAME_DELAY) {
                        image = f.Image;
                        last_frame_time = now;
                        return true;
                    }
                    //
                    // if duration exceeds delay, display image
                    if (frame_duration > rate) {
                        image = f.Image;
                        last_frame_time = now;
                        return true;
                    } else {
                        // too soon, wait...
                        image = null;
                        return false;
                    }
                } else {
                    // first image, display
                    last_frame_time = now;
                    image = f.Image;
                    return true;
                }
            } else {
                // no image available
                image = null;
                return false;
            }
        }

        private float lerp(float a, float b, float f) {
            return a*(1f - f) + b*f;
        }

发现我的错误。 我在base.getFrame()方法中计算时间,该方法仅在有可用帧时执行。 通过将测量值移到该块之外,它们会在每次渲染事件时更新,从而基于缓冲区内可用帧数创建一个平滑的时间步。

  • 仍然需要清理,但效果很好...

     private const int MAX_FRAME_DELAY = 500; private const float RATE_FACTOR = 0.01f; private long last_frame_time; private long last_update_time; private float rate; //============================= public override bool Get(out BitmapImage image) { PlaybackFrame f = null; long now = Environment.TickCount; if (last_frame_time > 0) { int count = getCount(); // int update_duration = (int)(now - last_update_time); int frame_duration = (int)(now - last_frame_time); // float target_rate = 0; if (count > 0) target_rate = update_duration / (float)count; // last_update_time = now; rate = lerp(rate, target_rate, RATE_FACTOR); // if (frame_duration >= MAX_FRAME_DELAY) { if (getFrame(out f)) { rate = MAX_FRAME_DELAY; last_frame_time = now; image = f.Image; return true; } else { image = null; return false; } } // if (frame_duration > rate) { if (getFrame(out f)) { last_frame_time = now; image = f.Image; return true; } else { image = null; return false; } } else { image = null; return false; } } else { if (getFrame(out f)) { last_frame_time = now; image = f.Image; return true; } else { image = null; return false; } } } private float lerp(float a, float b, float f) { return a*(1f - f) + b*f; } 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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