Go Up to Tutorial: FireMonkey Audio-Video
This tutorial demonstrates how to capture and display video data and how to customize the display of video data with FireMonkey.
- Select File > New > FireMonkey Desktop Application - Delphi > HD FireMonkey Application.
- Add a TLayout to the form. With the layout in focus, in the Object Inspector, set the Align property to
- Add the following to the TLayout:
- Change the name of the button to Start.
- Set Start as disabled by setting the Enable property of the button to False.
- Add a TImage to be used as support for displaying the captured data. Set the Align property of the image to
alCenter, in order that the video data is displayed on the center of the form.
- 1. Include the FMX.Media unit in the
// Delphi version of the implementation uses FMX.Media;
- 2. Declare a TVideoCaptureDevice public member, named VideoCamera, to the TForm1 class:
type TForm1 = class(TForm) // ............... public VideoCamera: TVideoCaptureDevice;
- 3. To be able to display the captured data to the image, add the SampleBufferReady and SampleBufferSync procedures to the TForm1 as public members. SampleBufferReady is the event handler associated to the OnSampleBufferReady event of the capturing device. It calls Synchronize to make sure that the display of the video data on the image is executed using the main thread, thereby avoiding multithread conflicts. SampleBufferSync explicitly buffers the video data on the image.
- There are the implementations for this two functions:
//Declaration TForm1 = class(TForm) //......... public //........ procedure SampleBufferSync; procedure SampleBufferReady(Sender: TObject; const ATime: TMediaTime); end; procedure TForm1.SampleBufferReady(Sender: TObject; const ATime: TMediaTime); begin TThread.Synchronize(TThread.CurrentThread, SampleBufferSync); //Resize the image so that the video is buffered in its original size Image1.Width:=Image1.Bitmap.Width; Image1.Height:=Image1.Bitmap.Height; end; procedure TForm1.SampleBufferSync; begin VideoCamera.SampleBufferToBitmap(Image1.Bitmap, true); end;
- 4. Populate the combo box the OnCreate event of the form with a list of all video devices connected to the station. Do this by using the GetDevicesByMediaType method. Access the method through Current property of the capturing device manager. This is the implementation:
procedure TForm1.FormCreate(Sender: TObject); var DeviceList: TCaptureDeviceList; i: integer; begin DeviceList := TCaptureDeviceManager.Current.GetDevicesByMediaType (TMediaType.Video); for i := 0 to DeviceList.Count - 1 do begin ComboBox1.Items.Add(DeviceList[i].Name); end; end;
- 5. On the OnChange event of the combo box, initialize VideoCamera by identifying the video device by name.
procedure TForm1.ComboBox1Change(Sender: TObject); begin VideoCamera := TVideoCaptureDevice (TCaptureDeviceManager.Current.GetDevicesByName(ComboBox1.Selected.Text)); if (VideoCamera <> nil) then begin StartButton.Enabled := true; end; end;
- 6. Double-click the Start button to attach OnClick event handlers to it. When the capturing process s running, the Start button is used to stop the process.
procedure TForm1.StartButtonClick(Sender: TObject); begin if (VideoCamera <> nil) then begin if (VideoCamera.State = TCaptureDeviceState.Stopped) then begin VideoCamera.OnSampleBufferReady := SampleBufferReady; VideoCamera.StartCapture; StartButton.Text := 'Stop'; end else begin VideoCamera.StopCapture; StartButton.Text := 'Start'; end; end else begin Caption := 'Video capture devices not available.'; end; end;
- 7. Make sure that the capturing device stops capturing if the form is closed when the capturing process is still working by calling the StopCapture method when the form is destroyed.
procedure TForm1.FormDestroy(Sender: TObject); begin if VideoCamera <> nil then VideoCamera.StopCapture; end;
Run the Application
- 1. To run the project, press F9.
- 2. Choose a video device from the combo box.
- 3. To start capturing data, press the Start button. The captured data will be displayed in the middle of the form.
Customize the captured image
In the next step, you can apply FireMonkey effects over the captured image in the current form.
- 1. To be able to choose different effects, add another TComboBox to the layout added above. Set it as being disabled by setting the Enable property of the button to False. It will be enabled when the capturing device starts working.
- 2. Populate the added combo box with the currently available FireMonkey effects using the TFilterManager. To have access to effects and filter, include the FMX.Filter and FMX.Filter.Effects units.
uses FMX.Media,FMX.Filter,FMX.Filter.Effects ;
- 3. Add as public members a TImageFXEffect component, named Effect, and a FillComboxEffect procedure. TImageFXEffect is the base class for all FireMonkey image effects and Effect is used to keep the effect currently applied.
- The FillComboxEffect procedure:
- Gets the list of currently available filters.
- Extracts the name of the filters.
- Builds the name of the effects from the filter's names (each filter has defined an effect.) You can see all effects in the Tool Palette, under Effects Category, or in the FMX.Filter.Effects unit.
- Adds the effect in the combo box list.
- This is the implementation:
procedure TForm1.FillComboxEffect(); var i, j, pos: integer; FiltersCategoryList, FilterList: TStrings; str: string; filterClass: TFilterClass; begin FiltersCategoryList := TStringList.Create; TFilterManager.FillCategory(FiltersCategoryList); for j := 0 to FiltersCategoryList.Count - 1 do begin FilterList := TStringList.Create; TFilterManager.FillFiltersInCategory(FiltersCategoryList[j], FilterList); i := 0; for i := 0 to FilterList.Count - 1 do begin str := FilterList[i]; pos := AnsiPos('Filter', str); if (pos <> 0) then Delete(str, pos, 6); str := 'T' + str + 'Effect'; ComboBox2.Items.Append(str); end; FilterList.Free; end; FiltersCategoryList.Free; ComboBox2.Items.Add('None'); ComboBox2.ItemIndex:=ComboBox2.Items.IndexOf('None'); end;
- 4. Call FillComboxEffect from the OnCreate event handler of the form.
- 5. Set the effect combo box as enabled from the OnChange event handler of the first combo box (the one used to choose the video device).
- 6. Add an OnChange event for the effect combo box, to apply the currently selected effect over the image. This is the implementation:
procedure TForm1.ComboBox2Change(Sender: TObject); var filterClass: TFmxObjectClass; begin if (ComboBox2.ItemIndex <> -1) then begin if Assigned(Effect) then Effect.Free; if (ComboBox2.Selected.Text <> 'None') then begin filterClass := TFmxObjectClass(FindClass(ComboBox2.Selected.Text)); if Assigned(filterClass) then begin Effect := TImageFXEffect(filterClass.Create(self)); Effect.Parent := Image1; end; end; end; end;
- 7. Run the project, start capturing, and observe how the effects are applied while the video data is captured and displayed.