Capture de la vidéo
Remonter à Tutoriel : Audio-vidéo dans FireMonkey
Ce tutoriel montre comment capturer et afficher des données vidéo et comment personnaliser l'affichage des données vidéo avec FireMonkey.
Sommaire
Conception de la fiche
- Sélectionnez Fichier > Nouveau > Application multi-périphérique - Delphi > Application vide.
- Ajoutez un TLayout sur la fiche. La disposition ayant la focalisation, dans l'inspecteur d'objets, définissez la propriété Align sur
MostBottom
. - Ajoutez les composants suivants au TLayout :
- Remplacez le nom du bouton par Start.
- Spécifiez que Start sera désactivé en définissant la propriété Enable du bouton sur False.
- Ajoutez un TImage qui sera utilisé comme support pour l'affichage des données capturées. Définissez la propriété Align de l'image sur
Center
afin que les données vidéo soient affichées au centre de la fiche.
Implémentation
- 1. Incluez l'unité FMX.Media :
Delphi :
// Delphi version of the implementation
uses
FMX.Media;
C++Builder :
// C++ version of the implementation
#include <FMX.Media.hpp>
- 2. Déclarez un membre public TVideoCaptureDevice nommé VideoCamera à la classe TForm1 :
Delphi :
type
TForm1 = class(TForm)
// ...............
public
VideoCamera: TVideoCaptureDevice;
C++Builder :
class TForm1 : public TForm
// ...............
public:
TVideoCaptureDevice* VideoCamera;
- 3. Pour que les données capturées puissent s'afficher dans l'image, ajoutez les procédures SampleBufferReady et SampleBufferSync à TForm1 en tant que membres publics. SampleBufferReady est le gestionnaire d'événement associé à l'événement OnSampleBufferReady du périphérique de capture. Il appelle Synchronize pour garantir que l'affichage des données vidéo sur l'image est exécuté en utilisant le thread principal, ce qui évite les conflits multithread. SampleBufferSync effectue explicitement la mise en mémoire tampon des données vidéo sur l'image.
- Voici les implémentations pour ces deux fonctions :
Delphi :
//Declaration
TForm1 = class(TForm)
//.........
public
//........
procedure SampleBufferSync;
procedure SampleBufferReady(Sender: TObject; const ATime: TMediaTime);
end;
// Implementation
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;
C++Builder :
// Declaration
class TForm1 : public TForm
//.........
public:
//.........
void __fastcall SampleBufferSync();
void __fastcall SampleBufferReady(TObject *Sender, const TMediaTime ATime);
// Implementation
void __fastcall TForm1::SampleBufferReady(TObject *Sender, const TMediaTime ATime) {
TThread::Synchronize(TThread::CurrentThread, (TThreadMethod)&SampleBufferSync);
// Resize the image so that the video is buffered in its original size
Image1->Width = Image1->Bitmap->Width;
Image1->Height = Image1->Bitmap->Height;
}
void __fastcall TForm1::SampleBufferSync() {
VideoCamera->SampleBufferToBitmap(Image1->Bitmap, true);
}
- 4. Remplissez la zone de liste déroulante de l'événement OnCreate de la fiche avec la liste de tous les périphériques vidéo connectés à la station de travail. Pour cela, utilisez la méthode GetDevicesByMediaType. Accédez à la méthode via la propriété Current du gestionnaire du périphérique de capture. Voici l'implémentation :
Delphi :
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;
C++Builder :
void __fastcall TForm1::FormCreate(TObject *Sender) {
TCaptureDeviceList DeviceList;
int i;
DeviceList = TCaptureDeviceManager::Current->GetDevicesByMediaType
(TMediaType::Video);
for (i = 0; i < DeviceList->Count; i++) {
ComboBox1->Items->Add(DeviceList->Items[i]->Name);
}
}
- 5. Sur l'événement OnChange de la zone de liste déroulante, initialisez VideoCamera en effectuant une identification du périphérique vidéo par son nom.
Delphi :
procedure TForm1.ComboBox1Change(Sender: TObject);
begin
VideoCamera := TVideoCaptureDevice
(TCaptureDeviceManager.Current.GetDevicesByName(ComboBox1.Selected.Text));
if (VideoCamera <> nil) then
begin
StartButton.Enabled := true;
end;
end;
C++Builder :
void __fastcall TForm1::ComboBox1Change(TObject *Sender) {
VideoCamera = dynamic_cast<TVideoCaptureDevice*>
(TCaptureDeviceManager::Current->GetDevicesByName(ComboBox1->Selected->Text));
if (VideoCamera != NULL) {
StartButton->Enabled;
}
}
- 6. Double-cliquez sur le bouton Start pour lui attacher des gestionnaires d'événement OnClick. Lorsque le processus de capture s'exécute, le bouton Start permet d'arrêter le processus.
Delphi :
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;
C++Builder :
void __fastcall TForm1::StartButtonClick(TObject *Sender) {
if (VideoCamera != NULL) {
if (VideoCamera->State == TCaptureDeviceState::Stopped) {
VideoCamera->OnSampleBufferReady = SampleBufferReady;
VideoCamera->StartCapture();
StartButton->Text = "Stop";
}
else {
VideoCamera->StopCapture();
StartButton->Text = "Start";
}
}
else
Caption = "Video capture devices not available.";
}
- 7. Assurez-vous que le périphérique de capture interrompt la capture si la fiche est fermée alors que le processus de capture continue, en appelant la méthode StopCapture à la destruction de la fiche.
Delphi :
procedure TForm1.FormDestroy(Sender: TObject);
begin
if VideoCamera <> nil then
VideoCamera.StopCapture;
end;
C++Builder :
void __fastcall TForm1::FormDestroy(TObject *Sender) {
if (VideoCamera != NULL) {
VideoCamera->StopCapture();
}
}
Exécuter l'application
- 1. Pour exécuter le projet, appuyez sur F9.
- 2. Choisissez le périphérique vidéo dans la zone de liste déroulante.
- 3. Pour commencer la capture des données, appuyez sur le bouton Start. Les données capturées s'affichent au milieu de la fiche.
Personnaliser l'image capturée
Lors de l'étape suivante, vous pouvez appliquer les effets FireMonkey à l'image capturée dans la fiche en cours.
- 1. Pour pouvoir choisir différents effets, ajoutez un autre TComboBox à la disposition ajoutée précédemment. Spécifiez qu'il sera désactivé en définissant la propriété Enable du bouton sur False. Il sera activé lorsque le périphérique de capture commencera à fonctionner.
- 2. Remplissez la zone de liste déroulante ajoutée avec les effets FireMonkey actuellement disponibles en utilisant TFilterManager. Pour avoir accès aux effets et au filtre, incluez les unités FMX.Filter et FMX.Filter.Effects.
Delphi :
uses
FMX.Media,FMX.Filter,FMX.Filter.Effects ;
C++Builder :
#include <FMX.Filter.hpp>
#include <FMX.Filter.Effects.hpp>
- 3. Ajoutez en tant que membres publics un composant TImageFXEffect nommé Effect et une procédure FillComboxEffect. TImageFXEffect est la classe de base pour tous les effets d'image FireMonkey et Effect est utilisé pour conserver l'effet actuellement appliqué.
- La procédure FillComboxEffect :
- Obtient la liste des filtres actuellement disponibles.
- Extrait le nom des filtres.
- Construit le nom des effets à partir des noms de filtres (chaque filtre a défini un effet). Vous pouvez voir tous les effets dans la palette d'outils sous la catégorie Effets ou dans l'unité FMX.Filter.Effects.
- Ajoute l'effet dans la liste de la zone de liste déroulante.
- Voici l'implémentation :
Delphi :
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;
C++Builder :
void __fastcall TForm1::FillComboxEffect() {
int i, j, pos;
TStrings *FiltersCategoryList, *FilterList;
String str;
TFilterClass filterClass;
FiltersCategoryList = new TStringList();
TFilterManager::FillCategory(FiltersCategoryList);
for (j = 0; j < FiltersCategoryList->Count; j++) {
FilterList = new TStringList();
TFilterManager::FillFiltersInCategory
(FiltersCategoryList->operator[](j), FilterList);
i = 0;
for (i = 0; i < FilterList->Count; i++) {
str = FilterList->operator[](i);
pos = AnsiPos("Filter", str);
if (pos != 0) {
str.Delete(pos, 6);
}
str = "T" + str + "Effect";
ComboBox2->Items->Append(str);
}
FilterList->Free();
}
FiltersCategoryList->Free();
ComboBox2->Items->Add("None");
ComboBox2->ItemIndex = ComboBox2->Items->IndexOf("None");
}
- 4. Appelez FillComboxEffect depuis le gestionnaire d'événement OnCreate de la fiche.
- 5. Définissez la zone de liste déroulante des effets comme activée depuis le gestionnaire d'événement OnChange de la première zone de liste déroulante (celle utilisée pour choisir le périphérique vidéo).
- 6. Ajoutez un événement OnChange pour la zone de liste déroulante des effets afin d'appliquer l'effet actuellement sélectionné sur l'image. Voici l'implémentation :
Delphi :
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;
C++Builder :
void __fastcall TForm1::ComboBox2Change(TObject *Sender) {
TFmxObjectClass filterClass;
if (ComboBox2->ItemIndex != -1) {
if (Effect != NULL) {
Effect->Free();
}
if (ComboBox2->Selected->Text != "None") {
filterClass = TFmxObjectClass(FindClass(ComboBox2->Selected->Text));
if (filterClass != NULL) {
Effect = dynamic_cast<TImageFXEffect *>(filterClass->InitInstance(this));
Effect->Parent = Image1;
}
}
}
}
- 7. Exécutez le projet, commencez la capture et observez comment les effets sont appliqués pendant la capture et l'affichage des données vidéo.