2016-07-07 16 views
0

これを実現するためにDelphi XE2とVFramesを使用してウェブカメラの写真を撮るプログラムをやっていますが、問題はすべてグラフィックアプリ正常に動作しますが、コンソールアプリケーションでこのユニットを使用すると、エラーが返されます。コンソールアプリケーションのVFramesを使用してウェブカメラでスクリーンショットを撮る

最初のチャンス例外は$ 76B6B727です。例外クラスEAccessViolationメッセージ 'アドレス違反が004A271Bモジュール' console.exe 'にあります。アドレス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

ちょうど:web_image.VideoStart(list_cams [0]); –

+1

その時点で 'list_cams [0]'とは何ですか? 'web_image'は有効ですか(nilではありません)?座っている場所に正確な設定がないので、コードをステップアップして変数を調べて絞り込むことはできません。あなたはその部分をする必要があります。そのコード行にブレークポイントを設定し、ブレークポイントまで実行します。変数を調べて、その値が何であるかを確認します。 '00000260'アドレスは、あなたがnilのオブジェクトのオブジェクトプロパティにアクセスする可能性が最も高いことを意味し、その行には2つのオブジェクトしかありません。どちらが無効ですか? –

答えて

1

VFramesユニットのreleventソースコードは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イベントを起動するために使用されるビデオ通知を受信するための隠しウィンドウを作成するため、メッセージループに依存します。コンソールアプリケーションにメッセージループがありません。そして、たとえそれがあったとしても、あなたのcapture_webcam()コードは、イベントが終了する前にイベントが発生するのを待っていないため、イベントが発生する前にTVideoImageオブジェクトを解放しています。

また、TVideoSampleクラス(内部ではTVideoImage)は、DirectShow APIを使用してウェブカメラのビデオストリームから画像をキャプチャします。 DirectShowはCOMベースのAPIです。 TVideoImageを使用する前に、コンソールアプリケーションがCOMを初期化していません。それだけでGetListOfDevices()が失敗し、空白のリストが返されます。とにかくそれを無視してデバイス名を指定しようとすると、TVideoSampleが作成中に作成できなかったCOMオブジェクトにアクセスしようとすると、VideoStart()はまだクラッシュします。

+0

説明をいただきありがとうございます。コンソールではできません。 –

+0

'VFrames.pas'ソースコードを変更して' Application.MainForm'依存関係を削除しない限り、あるいはあなたのアプリケーション用に 'MainForm'を作成しない限り、そうではありません。私が言及したすべてのものは、 'TVideoImage'以外のあなた自身のコードの問題なので、これらの問題を修正してください。 –

関連する問題