4

I have a Delphi 6 application that receives and processes an image stream from an external camera. I have the code on a background thread since it is CPU heavy and I don't want it interfering with with the user interface code that runs on the main thread. I want to update a rectangular area on a form or frame with the TBitmaps I create from the camera's JPEG frames that are received at a rate of 25 frames per second.

I want to know what method will give me the best performance and what Windows API calls or Delphi calls to use to do it. I would guess I should not use a TImage or TPicture or similar VCL component because they run on the main thread and I'm pretty sure trying to get anything done via a Synchronize() call is going to be inefficient and has the potential to slow down the threads involved. I would also want a technique that provides a smooth video display like double buffered controls do without any "striping" effects. Also, any tips on proper Canvas locking or device context management, etc. would be appreciated, especially tips on avoiding common mistakes in freeing resources.

Of course, a link to a good code sample that does what I need would be great.

Robert Oschler
  • 14,153
  • 18
  • 94
  • 227
  • 1
    In what way do you receive the image stream from the external camera ? direct show, or vfw ? Unless you have specific reasons to work with TBitmpas, I would try to use one of the direct show renderers as this is most likely the most CPU efficient way to render a camera image stream. – iamjoosy Jan 03 '12 at 07:13
  • I cannot give you any good code samples, but I can highly recommend looking at [Graphics32](http://graphics32.org/wiki/) for what you want to do. – iamjoosy Jan 03 '12 at 07:08

1 Answers1

3

AFAIK TBitmap are thread-safe, if you work only on its canvas. Synchronize is needed if you send GDI messages and need to refresh the screen, but from my experiment, using TBitmap.Canvas is just a wrapper around thread-safe Windows API. If you process the bitmap with pixel arithmetics (using e.g. Scanline), one unique bitmap per thread, you can do it on background.

But I suspect using TBitmap is not the most efficient way. Give a try to http://graphics32.org or http://aggpas.org which are very fast way to work on bitmaps.

If you can, as imajoosy proposed, the best way to process your input stream is to use direct X streaming process abilities.

For thread-safe process, if each thread is about to consume 100% of its core (which is very likely for image process), it is generally assumed that you shall better create NumberOfCPU-1 threads for your processing. For instance, you could create a pool of threads, then let those consume the bitmaps from the input stream.

Arnaud Bouchez
  • 42,305
  • 3
  • 71
  • 159
  • Why N-1? What not N? Take it to the extreme and consider a single core machine. That could never get anything done. Presumably the coordinating thread accounts for the -1 but most likely that sits idle almost all of the time and it's wasteful to reserve a whole core for that. – David Heffernan Jan 03 '12 at 09:49
  • @DavidHeffernan N-1 will mean 1 for a single core CPU, of course. This was a generic rule, to quote some common implementation pattern I've seen. Leaving one core unused is a good idea to let background system tasks (including antivirus and the main Windows/Desktop) working without any problem. And you may also add an upper limit (e.g. up to 4 threads if you have a 8 core CPU), depending on the rendering speed of each task (since e.g. it's well known that hyperthread cores are not the as efficient as "native" cores). With N or >N number of threads, overall processing speed will decrease. – Arnaud Bouchez Jan 03 '12 at 12:14
  • My experience is that saturating all N cores for such tasks gets the job done quickest. And modern hyperthreading cores are quite good. The latest Intel versions are worth using. I guess they got such a bad name last time round (deservedly so) that Intel don't even push the name anymore! – David Heffernan Jan 03 '12 at 12:16
  • @DavidHeffernan I think N or N-1 does not make a big difference, if it is <=N. It will depend on the real process of the thread. It's up to the OP to guess what is the best parameter, depending on real wall clock timing, after benchmarking on several hardware systems. – Arnaud Bouchez Jan 04 '12 at 10:01