如何使用 c# 編寫一個簡單的視頻播放器,以準確的 fps 播放視頻? (How to use c# to write a simple video player which plays the video with accurate fps?)


問題描述

如何使用 c# 編寫一個簡單的視頻播放器,以準確的 fps 播放視頻? (How to use c# to write a simple video player which plays the video with accurate fps?)

I'm write a simple video play with Emgu, which is a c# wrapper of opencv.

Now I can play a video, but I found the fps is not accurate, a little faster than normal.

In my code, I use Thread.sleep() to wait a while between 2 frames. The code is:

int fps = getFromFile(file); // which is 30
while (true) {
    var frame = CvInvoke.cvQueryFrame(capture);
    if (frame.ToInt32() == 0) break;

    Image<Bgr, byte> dest = new Image<Bgr, byte>(Convert.ToInt32(width), Convert.ToInt32(height));
    CvInvoke.cvCopy(frame, dest, IntPtr.Zero);
    box.Image = dest;

    Thread.Sleep(1000 / Convert.ToInt32(fps));
}

Where is wrong, and how to fix it?


update

The box in the code is Emgu.UI.ImageBox, which is thread‑safety, and I can access it from other thread directly: box.Image = dest

‑‑‑‑‑

參考解法

方法 1:

You need to keep a queue of frame objects 'topped up' and render them using a timer of some sort.  Usually, I would use a pool of frame objects that are continually recycled.

There is no simple video ‑ vlc.exe: 13 threads, realplay.exe: 19 threads, divX player: 23 threads.

方法 2:

My recommendation would be to use a timer

            _capture = new Capture(ofd.FileName);
            _videoTimer = new Timer();
            double fps = _capture.GetCaptureProperty(CAP_PROP.CV_CAP_PROP_FPS);
            _videoTimer.Interval =  Convert.ToInt16(1000 / fps); //the timer interval
            _videoTimer.Tick += new EventHandler(_videoTimer_Tick);
            _videoTimer.Start();

and now show this in an image box

private void _videoTimer_Tick(object sender, EventArgs e)
{
           Image<Bgr, Byte> img = _capture.QueryFrame();
            if (img == null) return; 
            box.Image = img;
}

方法 3:

Timing an event at very small and accurate intervals is no trivial task, and Thread.Sleep certainly isn't what you want here. 

First, Thread.Sleep doesn't guarantee your thread will resume in the specified amount of time, it just guarantees you'll be suspended for at least that amount. 

Secondly, most timers are not accurate at the millisecond level you need here. These include System.Threading.Timer and System.Timers.Timer. You'll get jerky framerate at best using these. My solution of choice would be to write my own event loop with lag compensation using System.Diagostics.Stopwatch. This is fairly difficult but a good example is given in OpenTK's GameWindow class. Another solution might the Multimedia Timers, but those are not directly available from .NET and I have no experience using these.

Thirdly, don't use the same thread to post rendering events every 33ms and to actually render the frames; have a separate thread render frames continuously into a queue, and have a the timer thread simply pick the front frame. That way you free up the timer thread and allow it to be as accurate as it needs to be.

(by FreewindMartin JamesMikosAsik)

參考文件

  1. How to use c# to write a simple video player which plays the video with accurate fps? (CC BY‑SA 3.0/4.0)

#video #emgucv #multithreading #OpenCV #C#






相關問題

當前在網站上放置音頻和視頻的最佳方式是什麼? (what's the current best way to put audio and video on a web site?)

相當於PNG的視頻? (Video equivalent of PNG?)

IOS - UISaveVideoAtPathToSavedPhotosAlbum 如何返回保存的視頻路徑? (IOS -how could UISaveVideoAtPathToSavedPhotosAlbum return the saved video path?)

如何使用 c# 編寫一個簡單的視頻播放器,以準確的 fps 播放視頻? (How to use c# to write a simple video player which plays the video with accurate fps?)

Monotouch - MoviePlayer 永遠不會超越“正在加載...” (Monotouch - MoviePlayer never gets beyond "loading...")

Android MediaMetadataRetriever setDataSource 失敗 (Android MediaMetadataRetriever setDataSource failed)

枚舉Windows上所有可用視頻編解碼器的最佳方法? (Best way to enumerate all available video codecs on Windows?)

如何通過上傳單個視頻文件為任何 html5 視頻獲得多種質量(360p、480p、720p)選擇 (how can i get multiple quality(360p,480p, 720p) selection for any html5 video with uploading single video file)

由於不支持的編解碼器,FFmpeg/Avconv 無法複製字幕? (FFmpeg/Avconv unable to copy subtitles due to unsupported codec?)

嵌入 youtube 視頻響應解決方案 (embed youtube video responsive solution)

如何輕鬆識別流是視頻還是圖片【ffmpeg庫】 (How to easily recognize whether stream is video or image [ffmpeg library])

livestream.com 如何顯示存檔的視頻? (how is livestream.com displaying the archived video(s)?)







留言討論