我正在使用.NET 4/C#基於Winforms的視頻播放器控件。我們已經收到了客戶的一些報告,但是,幀回放有時是不穩定的 - 每分鐘幾次播放會有明顯的滯後。顯示器是一個圖片盒 - 我們每40毫秒更換一次圖片(對於25fps視頻)。Windows窗體的圖片框不能可靠地刷新
修復了一些可能導致它(並使播放更平滑)的東西后,我們偶爾會看到放緩,特別是當窗口最大化時,我們需要繪製全尺寸的視頻播放器進行屏幕顯示。我注意到,在此場景中更新圖像後,Picturebox最多可能需要7-12ms才能刷新,並且影響非常明顯。
所以我嘗試了不同的方法,我們有兩個pictureboxes(PB1和PB2)。 PB1顯示當前幀,而PB2隱藏。然後,我們在下一幀解碼後立即更新PB2,並在顯示下一幀之前全部更新圖像。一旦它顯示下一幀的時間,我們顯示PB1並隱藏PB2。對於下一幀,我們更新PB1,顯示它並隱藏PB2。沖洗並重復。此操作需要1ms,但即使在測試應用程序中反覆顯示相同的兩個幀,我們仍然會發現全屏偶爾會出現滯後現象(儘管控制檯日誌顯示更新始終間隔40毫秒)。
這是Winforms本身的限制嗎?有沒有辦法獲得毫秒準確的更新控件?下面是我上面提到的代碼,用我們2個預裝的圖像之間交替,其中一個測試應用程序:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Bitmap image1;
private Bitmap image2;
private int i = 0;
public Form1()
{
InitializeComponent();
image1 = new Bitmap("image1.bmp");
image2 = new Bitmap("image2.bmp");
pictureBox1.Image = ResizeBitmap(image1, pictureBox1.Width, pictureBox1.Height);
pictureBox2.Image = ResizeBitmap(image2, pictureBox2.Width, pictureBox2.Height);
pictureBox1.Show();
pictureBox2.Hide();
}
public delegate void invoke();
private void redraw()
{
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
Console.WriteLine(DateTime.UtcNow.Millisecond);
stopwatch.Restart();
if (i % 2 == 0)
{
pictureBox1.BringToFront();
}
else
{
pictureBox2.BringToFront();
}
stopwatch.Stop();
Console.WriteLine("Bring to front: " + stopwatch.ElapsedMilliseconds);
Console.WriteLine(DateTime.UtcNow.Millisecond);
i++;
}
private Bitmap ResizeBitmap(Bitmap sourceBMP, int width, int height)
{
Bitmap result = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(result))
g.DrawImage(sourceBMP, 0, 0, width, height);
return result;
}
private void Form1_SizeChanged(object sender, EventArgs e)
{
pictureBox1.Show();
pictureBox2.Show();
pictureBox1.Image = ResizeBitmap(image1, pictureBox1.Width, pictureBox1.Height);
pictureBox2.Image = ResizeBitmap(image2, pictureBox2.Width, pictureBox2.Height);
pictureBox1.Refresh();
pictureBox2.Refresh();
}
private void Form1_Load(object sender, EventArgs e)
{
Action<object> action = (object obj) =>
{
while (true)
{
BeginInvoke(new invoke(redraw));
System.Threading.Thread.Sleep(40);
}
};
System.Threading.Tasks.Task t1 = new System.Threading.Tasks.Task(action, "a");
t1.Start();
}
}
}
時機點上,並沒有處理髮生的事情,可能會導致延遲。看來這個圖像盒每40ms就不能可靠地更新一次。
我正在考慮將視頻播放器移植到SFML(嵌入Winforms中),並且早期測試顯示沒有明顯的延遲,因此很有希望。然而,無論如何,要讓Picturebox可靠地更新,還是僅僅有幾毫秒的精度?
我知道這很有趣,試圖重新發明輪子,但你有沒有嘗試過使用優秀的老式嵌入式媒體播放器或VlcDotNet? http://msdn.microsoft.com/en-us/library/bb383953(v=vs.90).aspx http://vlcdotnet.codeplex.com/ – JuStDaN
不幸的是,這些並不適合我們的應用程序。它需要向後和向前的幀步進,這些步驟不提供以及定製覆蓋。該視頻播放器本身實際上已用於生產1 - 2年,除此問題外,其效果還不錯。目前看起來像更改爲SFML的繪圖可以工作。 – awr