我正在做一个程序来使用Delphi XE2和VFrame来拍摄网络摄像头来实现这个目标,问题是我已经弄明白了,在图形应用程序中一切正常,但是当我使用时在控制台应用程序中的单位,它返回错误说
76B6B727的首次机会异常。模块' console.exe'中的地址004A271B处的消息'访问冲突的异常类EAccessViolation。读取地址00000260'。处理console.exe(3676)
我的单位:
unit Webcam;
interface
uses SysUtils, Windows, Vcl.Imaging.Jpeg, Vcl.Graphics, VSample,
VFrames, Classes;
type
TWebcam = class
private
procedure NewVideoFrameEvent(Sender: TObject; Width, Height: integer;
DataPtr: pointer);
public
constructor Create;
destructor Destroy; override;
procedure capture_webcam(take_name: string);
end;
var
web_image: TVideoImage;
name_screen: string;
implementation
constructor TWebcam.Create;
begin
inherited Create;
end;
destructor TWebcam.Destroy;
begin
inherited Destroy;
end;
Procedure TWebcam.NewVideoFrameEvent(Sender: TObject; Width, Height: integer;
DataPtr: pointer);
var
bitmap: TBitmap;
name: string;
begin
name := name_screen;
if (FileExists(name)) then
begin
DeleteFile(Pchar(name));
end;
bitmap := TBitmap.Create;
bitmap.PixelFormat := pf24bit;
web_image.GetBitmap(bitmap);
bitmap.SaveToFile(name);
bitmap.Free;
web_image.VideoStop;
web_image.Free;
end;
procedure TWebcam.capture_webcam(take_name: string);
var
list_cams: TStringList;
begin
web_image := TVideoImage.Create();
list_cams := TStringList.Create;
web_image.GetListOfDevices(list_cams);
if not(list_cams.count = 0) then
begin
name_screen := take_name;
web_image.VideoStart(list_cams[0]);
end;
list_cams.Free;
web_image.OnNewVideoFrame := NewVideoFrameEvent;
end;
end.
控制台:
program console;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Webcam;
var
webcamz: TWebcam;
begin
try
webcamz := TWebcam.Create();
webcamz.capture_webcam('test.jpg');
webcamz.Free();
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
我该怎么办?
答案 0 :(得分:1)
VFrames
单元的相关源代码可在Github上找到:
https://github.com/heise/GRBLize/blob/edge/VFrames.pas
https://github.com/heise/GRBLize/blob/edge/VSample.pas
TVideoImage.VideoStart()
方法依赖于Application.MainForm.Handle
。默认情况下,控制台应用程序没有MainForm
,因此除非您创建MainForm
(这会破坏创建控制台应用程序的目的),否则它将导致控制台应用程序中的代码崩溃。
除此之外,TVideoImage
还依赖于消息循环,因为它会创建一个隐藏窗口来接收用于触发OnNewVideoFrame
事件的视频通知。您的控制台应用程序没有消息循环。即使它确实如此,你仍然会在事件发生之前释放TVideoImage
对象,因为你的capture_webcam()
代码在退出之前没有等待事件发生。
此外,TVideoSample
类(TVideoImage
内部使用)使用DirectShow API从网络摄像头的视频流中捕获图像。 DirectShow是一个基于COM的API。在使用TVideoImage
之前,您的控制台应用程序未初始化COM。仅此一项将导致GetListOfDevices()
失败并返回空白列表。如果您试图忽略它并提供设备名称,VideoStart()
在尝试访问TVideoSample
在构造期间无法创建的COM对象时仍会崩溃。