【发布时间】:2011-08-26 22:28:26
【问题描述】:
我有一些代码可以以 720p 和 24fps 的速度从摄像机流式传输视频。我试图在代码中捕获这个流,并最终通过将压缩的 jpeg 组合成 mjpeg 等来创建它的视频。我遇到的问题是这个整体代码不够快,无法以 24 fps 或 0.04 秒的速度创建每个图像。
使用
Stopwatch();
我发现内部 for 循环每个循环需要 0.000000000022 秒。
外部 for 循环需要 0.0000077 秒才能完成每个循环。
我发现从开始到图像保存的整个功能每次运行运行 0.21 秒。
从内部循环计算以完成图像:
.000000000022 x 640 = .000000001408 seconds
.000000001408 x 360 = .00000050688 seconds
从外部循环计算以完成图像:
.0000077 x 360 = .002772 seconds
如果我可以创建与那些时间相关的图像,我将被设置,但运行整个代码的代码需要 0.21 秒才能完成所有代码
temp_byte1 = main_byte1;
temp_byte2 = main_byte2;
timer1.Reset();
timer1.Start();
Bitmap mybmp = new Bitmap(1280, 720);
BitmapData BPD = mybmp.LockBits(new Rectangle(0, 0, 1280, 720), ImageLockMode.WriteOnly, mybmp.PixelFormat);
IntPtr xptr = BPD.Scan0;
IntPtr yptr = BPD.Scan0;
yptr = new IntPtr( yptr.ToInt64() + (1280 * 720 * 2));
int bytes = Math.Abs(BPD.Stride);
byte[][] rgb = new byte[720][];
int Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8;
int U1, U2, V1, V2, U3, U4, V3, V4;
for (int one = 0; one < 360; one++)
{
timer2.Reset();
timer2.Start();
rgb[one] = new byte[bytes];
rgb[360 + one] = new byte[bytes];
for (int two = 0; two < 640; two++)
{
timer3.Reset();
timer3.Start();
U1 = temp_byte1[one * 2560 + 4 * two + 0];
Y1 = temp_byte1[one * 2560 + 4 * two + 1];
V1 = temp_byte1[one * 2560 + 4 * two + 2];
Y2 = temp_byte1[one * 2560 + 4 * two + 3];
U2 = temp_byte2[one * 2560 + 4 * two + 0];
Y3 = temp_byte2[one * 2560 + 4 * two + 1];
V2 = temp_byte2[one * 2560 + 4 * two + 2];
Y4 = temp_byte2[one * 2560 + 4 * two + 3];
RGB_Conversion(Y1, U1, V1, two * 8 + 0, rgb[one]);
RGB_Conversion(Y2, U1, V1, two * 8 + 4, rgb[one]);
RGB_Conversion(Y3, U2, V2, two * 8 + 0, rgb[(360 + one)]);
RGB_Conversion(Y4, U2, V2, two * 8 + 4, rgb[(360 + one)]);
timer3.Stop();
timer3_[two] = timer3.Elapsed;
}
Marshal.Copy(rgb[one], 0, xptr, 5120);
xptr = new IntPtr(xptr.ToInt64() + 5120);
Marshal.Copy(rgb[(360 + one)], 0, yptr, 5120);
yptr = new IntPtr(yptr.ToInt64() + 5120);
timer2.Stop();
timer2_[one] = timer2.Elapsed;
}
mybmp.UnlockBits(BPD);
mybmp.Save(GetDateTimeString("IP Pictures") + ".jpg", ImageFormat.Jpeg);
代码有效,它将 yuv422 传入的字节数组转换为完整大小的 jpeg,但无法理解为什么 for 循环的速度与整个代码之间存在如此差异
我搬家了
byte[][]rgb = new byte[720];
rgb[x] = new byte[bytes];
到在程序启动时获取 init 而不是每个函数调用/运行的全局没有可测量的速度增加。
更新
RGB 转换:接受 YUV 并将其转换为 RGB 并将其放入保存值的全局数组中
public void RGB_Conversion(int Y, int U, int V, int MULT, byte[] rgb)
{
int C,D,E;
int R,G,B;
// create the params for rgb conversion
C = Y - 16;
D = U - 128;
E = V - 128;
//R = clamp((298 x C + 409 x E + 128)>>8)
//G = clamp((298 x C - 100 x D - 208 x E + 128)>>8)
//B = clamp((298 x C + 516 x D + 128)>>8)
R = (298 * C + 409 * E + 128)/256;
G = (298 * C - 100 * D - 208 * E + 128)/256;
B = (298 * C + 516 * D + 128)/256;
if (R > 255)
R = 255;
if (R < 0)
R = 0;
if (G > 255)
G = 255;
if (G < 0)
G = 0;
if (B > 255)
B = 255;
if (B < 0)
B = 0;
rgb[MULT + 3] = 255;
rgb[MULT + 0] = (byte)B;
rgb[MULT + 1] = (byte)G;
rgb[MULT + 2] = (byte)R;
}
【问题讨论】:
-
您是否尝试过单独对循环的外部部分进行计时?一个电话可能会占用大部分时间。
-
是的。我一直在慢慢地这样做,并挑选出减缓它的因素,要么将其移除,要么在不会影响这次的更全球性的空间中进行。仍在尝试这样做,但让其他人也看看会有所帮助,因为我自己越来越沮丧。一次代码需要 x 秒才能完成,下一次,相同的东西需要 100x 秒 =\
-
我认为这可能是在最后调用
Save- 磁盘访问。 -
还可以查看编译器使用反射器或 ilspy 生成的内容;有时您认为是优化,编译器会忽略并按其方式进行操作,即所有这些(一 * 2560 + 4 * 二)甚至可能变成一个变量。我还发现编组很昂贵,尝试使用 BitConvertor 处理 ints 等简单类型。
-
您是否意识到 JPEG 通常是 YUV 并且只会将您的色彩空间转换回来?
标签: c# performance optimization