2016-07-07 110 views
0

我正在做一个程序,使用Delphi XE2和VFrames来拍摄网络摄像头的图片来实现此目的,问题是我已经搞清楚了,在一个图形应用程序中,工作正常,但是当我使用单位在控制台应用程序,它返回我错误说使用控制台应用程序中的VFrame在网络摄像机中使用屏幕截图

第一次机会异常在$ 76B6B727。异常类EAccessViolation消息'模块'console.exe'中地址为004A271B的访问冲突。阅读地址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

使用调试器来遍历代码。哪条线特别提出了例外? –

+0

Just in:web_image.VideoStart(list_cams [0]); –

+1

那么在那个时候什么是'list_cams [0]'? 'web_image'是否有效(而不是无)?我们没有准确的安装位置,所以我们无法逐步检查代码并检查变量以缩小它的范围。你需要做那部分。在该行代码中设置断点并运行到断点。然后检查变量以查看它们的值。 '00000260'地址意味着你很可能访问一个零对象的对象属性,并且你只在该行中有几个对象。哪一个是无效的? –

回答

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也对消息循环具有依赖性,因为它会创建一个隐藏窗口来接收用于触发事件的视频通知。您的控制台应用程序没有消息循环。即使这样做,您仍然可以在事件发生之前释放TVideoImage对象,因为您的capture_webcam()代码不会在退出之前等待事件触发。

此外,TVideoSample类(其中TVideoImage内部使用)使用DirectShow API从网络摄像机的视频流捕获图像。 DirectShow是一个基于COM的API。在使用TVideoImage之前,您的控制台应用程序未初始化COM。仅此一项就会导致GetListOfDevices()失败并返回空白列表。如果你试图忽略它并提供一个设备名称,VideoStart()在尝试访问一个COM对象时仍然会崩溃,而这个COM对象在构建过程中不能创建。

+0

好的,感谢您的解释,然后我不能在控制台中做? –

+0

除非您更改'VFrames.pas'源代码以除去Application.MainForm依赖项,否则为您的应用程序创建一个MainForm。我提到的其他一切都是在你自己的'TVideoImage'之外的代码中出现的问题,所以请解决这些问题。 –

相关问题