Back in days I was able to use web cam within my delphi apps using DirectX header translations for Delphi.
Now Firemonkey offers an access to all video/audio capture devices via FMX.Media. I have VCL app and I wanted to use Firemonkey to access camera. I included FMX.Media in my camera unit and used TVideoCaptureDevice class. When getting bitmap from camera it's in Firemonkey bitmap format so I had to convert it to VCL bitmap format with a small trick. Then I draw it to Image on my form.
Everything works perfect but when I shut down an application I get a memory leak report. EurekaLog call stack points to FMX.Context.DX9 in CreateSharedDevice. I checked everything in my code and it looks fine so I am not directly making any memory leaks.
Is that memory leak because I am using FMX.Media in my VCL and it's intention is not to used it in VCL apps due to some conceptual differences? Has anyone else experienced it? By the way I am using Delphi XE6.
Thanks for your help and answers.
OnCreateForm:
CamImage := TImage.Create(Self);
CamImage.Parent := pnlContainer;
CamImage.Align := alClient;
CamImage.Stretch := true;
CamImage.AutoSize := false;
FMX_BMP := FMX.Graphics.TBitmap.Create;
VCL_BMP := VCL.Graphics.TBitmap.Create;
Surface := TBitmapSurface.Create;
Stream := TMemoryStream.Create;
OnDestroyForm:
if VideoCamera <> nil then
begin
VideoCamera.OnSampleBufferReady := nil;
VideoCamera.StopCapture;
end;
Stream.Free;
Surface.Free;
FMX_BMP.Free;
VCL_BMP.Free;
Populating TPopUpMenu with camera names:
DeviceList := TCaptureDeviceManager.Current.GetDevicesByMediaType (TMediaType.Video);
for Idx := 0 to DeviceList.Count - 1 do
begin
MenuItem := CreateMenuItem(pmCameras, DeviceList[Idx].Name, false, false, false, 0, 0, pmCameras, evtSelectCamera);
MenuItem.AutoHotkeys := maManual;
pmCameras.Items.Add(MenuItem);
end;
Event handler for selecting camera from TPopup:
procedure TCameraGraph.evtSelectCamera(Sender: TObject);
var Item: TMenuItem;
begin
if Sender is TMenuItem then
begin
Item := Sender as TMenuItem;
PrevCam := Item.Caption;
VideoCamera := TVideoCaptureDevice(TCaptureDeviceManager.Current.GetDevicesByName(StripHotkey(Item.Caption)));
Item.Checked := true;
btnCamera.Caption := Item.Caption;
RefreshMenuFonts;
if (VideoCamera.State = TCaptureDeviceState.Stopped) then
begin
VideoCamera.OnSampleBufferReady := SampleBufferReady;
VideoCamera.StartCapture;
end else
begin
VideoCamera.OnSampleBufferReady := nil;
VideoCamera.StopCapture;
end;
end;
end;
Event handler for TVideoCaptureDevice.OnSampleBufferReady:
procedure TCameraGraph.SampleBufferReady(Sender: TObject; const ATime: TMediaTime);
begin
TThread.Synchronize(TThread.CurrentThread, SampleBufferSync);
end;
And finally getting firemonkey bitmap and converting it into VCL bitmap and displaying it:
procedure TCameraGraph.SampleBufferSync;
begin
VideoCamera.SampleBufferToBitmap(FMX_BMP, true);
Surface.Assign(FMX_BMP);
TBitmapCodecManager.SaveToStream(Stream, Surface, 'bmp');
Stream.Seek(0, TSeekOrigin.soBeginning);
VCL_BMP.LoadFromStream(Stream);
CamImage.Picture.Graphic := VCL_BMP;
end;