Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I wrote the following program:</p> <pre><code>{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, Vcl.Graphics, Vcl.Imaging.jpeg, System.IOUtils, System.Diagnostics; var i: Integer; bmp: TBitmap; jpeg: TJPEGImage; Stopwatch: TStopwatch; begin bmp := TBitmap.Create; bmp.SetSize(1280, 760); jpeg := TJPEGImage.Create; Stopwatch := TStopwatch.StartNew; for i := 1 to 100 do begin jpeg.Assign(bmp); jpeg.SaveToFile('C:\desktop\temp\'+TPath.GetRandomFileName); end; Writeln(Stopwatch.ElapsedMilliseconds); Readln; end. </code></pre> <p>It converts 1280x760 pixel bitmaps to JPEG images, and then saves to disk. It does so 100 times. On my machine this takes 9 seconds. That's a throughput of 11 images per second. If I skip the convert to JPEG step and save the bitmap directly I can get a through put of 150 images per second. Clearly the conversion to JPEG is a bottleneck.</p> <p>You are looking for 30 images per second. Whilst multi-threading helps, I suspect you have a quad core machine. One processor for the webcam, and three for the saving. So if you only have three threads available, then you are probably going to struggle to reach the required throughput of 30 frames per second. Theoretical peak on my machine would be 33. If you don't achieve 30 frames per second then your queue will obviously overflow.</p> <p>The obvious conclusion is that you need to find a faster JPEG conversion library. I'm quite sure that such libraries exist. For example, I think that <code>libjpeg</code> should be a lot faster.</p> <p>As for your existing code there are some obvious flaws:</p> <ol> <li><code>Sleep</code> should usually be avoided. In your case it is suicidal to sleep if the last attempt to pull an image succeeded. Don't do that. You should use a real threaded queue. One that allow proper blocking waits on synchronization objects. It's actually pretty trivial to make one yourself using event objects and your favourite non-threaded queue.</li> <li>You are holding the lock whilst calling <code>TElement.Create(bmWebcam)</code>. That is going to hinder scaling. Assign <code>TElement.Create(bmWebcam)</code> to a local variable, outside the lock. And then assign to the shared data inside the lock.</li> </ol> <p>So, you could check these ideas out by first of all removing the call to <code>Sleep</code>. And then changing <code>TWebcam.OnSave</code> to look like this:</p> <pre><code>Procedure TWebcam.OnSave(Sender:TObject; bmWebcam:TBitmap); var NewElement: TElement; begin NewElement := TElement.Create(bmWebcam); EnterCriticalSection(CritSect); inc(iElementsLength); vElements[iElementsLength] := NewElement; LeaveCriticalSection(CritSect); end; </code></pre> <p>These suggestions will help a little, but I think you'll need to tackle the fundamental problem, namely the JPEG conversion.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload