Я пытаюсь отправить поток изображений jpg с камеры Android на клиента, используя Indy 10, я получил пример CameraComponent из Delphi, который получает изображение с камеры и показать в TImage, то, что я хотел бы сделать, это отправить этот поток клиенту, используя IdTCPClient.Delphi - отправка потока с использованием IdCmdTCPServer для клиента
Я использую IdCmdTCPServer для отправки потока, который требуется клиенту для данных, но когда я запускаю серверное приложение на своем Android-устройстве (Galaxy S4 mini), приложение работает слишком медленно, изображение отображается с помощью обновления камеры медленный, я могу подключиться к серверу, но отправляется только одно изображение, а затем серверное приложение перестает отвечать.
Я думаю, что моя проблема связана с несколькими потоками, однако я не могу понять, как ее решить. Вот мой код.
unit uMain;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, FMX.Media,
FMX.Platform, FMX.Objects, FMX.Layouts, FMX.Memo,FMX.Controls.Presentation,
System.Generics.Collections,
System.IOUtils, IdCmdTCPServer,
IdCommandHandlers, IdContext, IdStack, IdBaseComponent, IdComponent,
IdCustomTCPServer, IdTCPServer, FMX.ScrollBox, IdIOHandler, IdIOHandlerStream,
IdCustomHTTPServer, IdHTTPServer, IdUDPBase, IdUDPServer, IdTCPConnection,
IdSimpleServer;
type
TCameraComponentForm = class(TForm)
CameraComponent1: TCameraComponent;
btnStartCamera: TButton;
imgCameraView: TImage;
btnFrontCamera: TSpeedButton;
btnBackCamera: TSpeedButton;
Memo1: TMemo;
IdCmdTCPServer1: TIdCmdTCPServer;
procedure btnStartCameraClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure CameraComponent1SampleBufferReady(Sender: TObject;
const ATime: TMediaTime);
procedure btnFrontCameraClick(Sender: TObject);
procedure btnBackCameraClick(Sender: TObject);
procedure IdCmdTCPServer1Connect(AContext: TIdContext);
procedure IdCmdTCPServer1Disconnect(AContext: TIdContext);
procedure IdCmdTCPServer1CommandHandlers0Command(ASender: TIdCommand);
private
{ Private declarations }
imag: TMemoryStream;
Enable_Stream: Boolean;
Camera_enable: Boolean;
procedure GetImage;
procedure SendStream;
public
{ Public declarations }
function AppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean;
end;
var
CameraComponentForm: TCameraComponentForm;
implementation
{$R *.fmx}
{$R *.NmXhdpiPh.fmx ANDROID}
procedure TCameraComponentForm.FormCreate(Sender: TObject);
var
AppEventSvc: IFMXApplicationEventService;
begin
Camera_enable:= False;
// Stream to be sent
imag:= TMemoryStream.Create;
Enable_Stream:= False;
// Start server
IdCmdTCPServer1.Active:= True;
{ by default, we start with Front Camera and Flash Off }
CameraComponent1.Kind := FMX.Media.TCameraKind.ckFrontCamera;
if CameraComponent1.HasFlash then
CameraComponent1.FlashMode := FMX.Media.TFlashMode.fmFlashOff;
CameraComponent1.CaptureSettingPriority := TVideoCaptureSettingPriority.FrameRate;
{ Add platform service to see camera state. }
if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, IInterface(AppEventSvc)) then
AppEventSvc.SetApplicationEventHandler(AppEvent);
end;
procedure TCameraComponentForm.Timer1Timer(Sender: TObject);
begin
imgCameraView.Repaint;
end;
{ Make sure the camera is released if you're going away.}
function TCameraComponentForm.AppEvent(AAppEvent: TApplicationEvent;
AContext: TObject): Boolean;
begin
case AAppEvent of
TApplicationEvent.WillBecomeInactive:
CameraComponent1.Active := False;
TApplicationEvent.EnteredBackground:
CameraComponent1.Active := False;
TApplicationEvent.WillTerminate:
CameraComponent1.Active := False;
end;
end;
procedure TCameraComponentForm.btnBackCameraClick(Sender: TObject);
begin
{ select Back Camera }
CameraComponent1.Active := False;
CameraComponent1.Kind := FMX.Media.TCameraKind.BackCamera;
CameraComponent1.Active := True;
end;
procedure TCameraComponentForm.btnFrontCameraClick(Sender: TObject);
begin
{ select Front Camera }
CameraComponent1.Active := False;
CameraComponent1.Kind := FMX.Media.TCameraKind.FrontCamera;
CameraComponent1.Active := True;
end;
procedure TCameraComponentForm.btnStartCameraClick(Sender: TObject);
begin
if Camera_enable = False then
begin
Camera_enable:= True;
{ turn on the Camera }
CameraComponent1.Active := True;
end
else
begin
Camera_enable:= False;
{ turn off the Camera }
CameraComponent1.Active := False;
end;
end;
procedure TCameraComponentForm.CameraComponent1SampleBufferReady(
Sender: TObject; const ATime: TMediaTime);
begin
// Update the TImage
TThread.Synchronize(TThread.CurrentThread, GetImage);
// Save the bitmap to stream and send to client
imgCameraView.Bitmap.SaveToStream(imag);
if Enable_Stream then
SendStream;
//imgCameraView.Width := imgCameraView.Bitmap.Width;
//imgCameraView.Height := imgCameraView.Bitmap.Height;
end;
procedure TCameraComponentForm.GetImage;
begin
CameraComponent1.SampleBufferToBitmap(imgCameraView.Bitmap, True);
end;
procedure TCameraComponentForm.IdCmdTCPServer1CommandHandlers0Command(
ASender: TIdCommand);
begin
Memo1.Lines.Add('Send Stream');
Enable_Stream:= True;
end;
procedure TCameraComponentForm.IdCmdTCPServer1Connect(AContext: TIdContext);
begin
Memo1.Lines.Add('Connection being made - '+ AContext.Connection.Socket.Binding.PeerIP);
end;
procedure TCameraComponentForm.IdCmdTCPServer1Disconnect(AContext: TIdContext);
begin
Memo1.Lines.Add('Disconnection being made - '+ AContext.Connection.Socket.Binding.PeerIP);
end;
procedure TCameraComponentForm.SendStream;
var
index: integer;
begin
// Write to the client in a thread safe way
with IdCmdTCPServer1.Contexts.LockList do
try
for index := 0 to Count - 1 do
begin
TIdContext(Items[index]).Connection.IOHandler.WriteLn('Stream');
TIdContext(Items[index]).Connection.IOHandler.Write(imag,0,True);
end;
finally
IdCmdTCPServer1.Contexts.UnlockList;
end;
end;
end.
Я думаю, что потоки из CameraComponent и сервера не синхронизированы, но я не знаю, как решить эту проблему и ускорить приложение.
Любая помощь приветствуется.
Привет Remy, спасибо так много для точки меня, кстати, код, который вы сделали работали его, теперь TImage обновляется быстро, пока сервер Безразлично» t есть соединение, потому что, когда соединение выполняется и поток начинает отправляться, скорость обновления изображения снова становится медленной, на сервере и клиенте - почти на 1 кадр за секунду. Видел, мне нужно немного поработать над этими tthreads, мой вопрос: я работаю с IdCmdTCPServer, если я использую IdTCPServer или IdUDPServer может ускорить передачу? Следовательно, скорость обновления изображения. –
Я ничего не знаю о 'TCameraComponent' или о том, как это работает. Если он обновляет изображения с высокой скоростью, повторяющиеся вызовы 'TThread.Synchronize()' скорее всего замедляют работу. Теперь я изменил их на 'TThread.Queue()'. И нет, переход на 'TIdTCPServer' не ускорит что-либо. Переключение на 'TIdUDPServer' или' TIdIPMCastServer' может, хотя, поскольку вы можете отправлять трансляции по подсети/многоадресной рассылке, а не беспокоиться о потоковой передаче. –