libvlcwrapperの機能を少しだけ拡張

libvlc_video_take_snapshot()を追加

libvlcwrapperでライブ動画を再生中にスナップショットをセーブする必要が生じました。CS-CP1等のAPIを叩いてスナップショットを撮ることを考えましたが、どうも実現できません。ということでUSB直結のwebcameraを使うことにしました。前の記事でも何回か取り上げましたが、WindowsシステムないしVLC界隈からはCapture Deviceで扱えます。VLCでいうところのMRLとしては、“dshow://”ですね。

フォームは、

今はこれだけ。TPanelx1,TButtonx1,TLabelx1ですね。Unit1.hは、

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TPanel *Panel1;
	TButton *Still;
	TLabel *Label1;
	void __fastcall FormDestroy(TObject *Sender);
	void __fastcall StillClick(TObject *Sender);
private:	// ユーザー宣言
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

Unit1.cppは、

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include "vlcwrapper.h"
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

TForm1 *Form1;
VLC* vlc;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	AnsiString mrl = "dshow://";


	vlc = new VLC(mrl);
	vlc->Option(":dshow-aspect-ratio=16\\:9");
	vlc->SetHWND(Form1->Panel1->Handle);
	vlc->Play();

}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormDestroy(TObject *Sender)
{
	vlc->Stop();
	delete vlc;
}


void __fastcall TForm1::StillClick(TObject *Sender)
{
	AnsiString output_path = "webcam_snapshot.png";
	int result = vlc->SnapShot(output_path.c_str());

	if (result == 0) {
		Label1->Caption = "File saved";
	} else {
        Label1->Caption = "save error";
	}

}
//---------------------------------------------------------------------------

/*
	vlc = new VLC("dshow://");
	vlc->Option(":dshow-vdev=" + dlist[Form1->ComboBox1->ItemIndex].dname);
	String resolution = dlist[Form1->ComboBox1->ItemIndex].resolutions[Form1->ComboBox2->ItemIndex];
	TStringDynArray array = SplitString(resolution, "x");
	vlc->Option(":dshow-size=" + dlist[Form1->ComboBox1->ItemIndex].resolutions[Form1->ComboBox2->ItemIndex]);
	//vlc->Option(":dshow-aspect-ratio=4\\:3");
	Edit1->Text = array[0];
	Edit2->Text = array[1];

	vlc->Option(":dshow-aspect-ratio="+Edit1->Text+"\\:"+Edit2->Text);
	if( !Floating->Checked )
		vlc->SetHWND(Panel1->Handle);
	vlc->SetVolume(25);
	vlc->Play();

*/

忘れずにプロジェクトにvlcwrapper.hを追加し、ターゲットプラットフォームは64bitで、

こんな感じです。vlcwrapper.hにはlibvlc_video_take_snapshot()を追加しています。追加部分だけ示してもいいのですが、3カ所追加するので間違いやすいということで、全部掲載しておきます。

#ifndef vlcwrapper
#define vlcwrapper

#ifndef _WIN64
#error compile 64bit mode
#endif
#include <vcl.h>
#include <vlc/vlc.h>
#include <windows.h>
#include <Registry.hpp>


class VLC {
	private:

   //	typedef void WINAPI (*plibvlcmediaaddoption)(libvlc_instance_t*,const char*);
  // LIBVLC_API void 	libvlc_media_player_pause (libvlc_media_player_t *p_mi)

	typedef int WINAPI (*plibvlcvideotakesnapshot)(libvlc_media_player_t *,int,const char*,int,int);
	typedef void WINAPI (*plibvlcmediaplayerpause)(libvlc_media_player_t *);
	typedef int  WINAPI (*plibvlc_audio_set_volume)(libvlc_media_player_t*,int);
	typedef libvlc_instance_t* WINAPI (*plibvlcnew)(int , const char*);
	typedef libvlc_media_t* WINAPI (*plibvlcmedianewlocation)(libvlc_instance_t* , const char*);
	typedef libvlc_media_player_t* WINAPI (*plibvlcmediaplayernewfrommedia)(libvlc_media_t*);
	typedef void WINAPI (*plibvlcmediarelease)(libvlc_media_t*);
	typedef void WINAPI (*plibvlcvideosetscale)(libvlc_media_player_t*,float);
	typedef void WINAPI (*plibvlcmediaplayerplay)(libvlc_media_player_t*);
	typedef void WINAPI (*plibvlcmediaaddoption)(libvlc_media_t*,const char*);
	typedef bool WINAPI (*plibvlcmediaplayerisplaying)(libvlc_media_player_t *);
	typedef void WINAPI (*plibvlcmediaplayersethwnd)(libvlc_media_player_t *,HWND);
	typedef void WINAPI (*plibvlcmediaplayerstop)(libvlc_media_player_t*);
	typedef void WINAPI (*plibvlcmediaplayerrelease)(libvlc_media_player_t*);
	typedef void WINAPI (*plibvlcrelease)(libvlc_instance_t*);

	HMODULE avlccore;
	HMODULE avlc;

	//plibvlcmediaaddoption libvlc_media_add_option;
	plibvlcvideotakesnapshot libvlc_video_take_snapshot;
	plibvlcmediaplayerpause libvlc_media_player_pause;
	plibvlc_audio_set_volume libvlc_audio_set_volume;

	plibvlcnew libvlc_new;
	plibvlcmedianewlocation libvlc_media_new_location;
	plibvlcmediaplayernewfrommedia libvlc_media_player_new_from_media;
	plibvlcmediarelease libvlc_media_release;
	plibvlcmediaplayerplay libvlc_media_player_play;
	plibvlcmediaplayersethwnd libvlc_media_player_set_hwnd;
	plibvlcvideosetscale libvlc_video_set_scale;
	plibvlcmediaaddoption libvlc_media_add_option;
	plibvlcmediaplayerisplaying libvlc_media_player_is_playing;
	plibvlcmediaplayerstop libvlc_media_player_stop;
	plibvlcmediaplayerrelease libvlc_media_player_release;
	plibvlcrelease libvlc_release;


		libvlc_media_player_t* media_player;
		libvlc_instance_t* instance;
		libvlc_media_t* VlcMedia;

	AnsiString GetVLCLibPath()
	{
	AnsiString S;
	AnsiString KeyName = "Software\\VideoLAN\\VLC";

	TRegistry *Registry = new TRegistry(KEY_READ);
	try {
		Registry->RootKey = HKEY_LOCAL_MACHINE;
		Registry->OpenKey(KeyName, false);
		S = Registry->ReadString("InstallDir");
	}
	__finally {
		delete Registry;
	}
	return S;

	}

	void initaddress(){
			AnsiString path;
			char buf[100];

		path = GetVLCLibPath();

		//ShowMessage(path);

		path += "\\";

		AnsiString p1 = path + "libvlc.dll";
		AnsiString p2 = path + "libvlccore.dll";


		avlccore = LoadLibraryA(p2.c_str());
	avlc = LoadLibraryA(p1.c_str());

	if( !avlc )
		ShowMessage("libvlc.dll loading error");

	if( !avlccore )
		ShowMessage("libvlccore.dll loading error");

	FARPROC proc0 = GetProcAddress(avlc,"libvlc_media_player_pause");
	if(proc0 == NULL ){
		ShowMessage("getting libvlc_media_player_pause is failed");
	}

	libvlc_media_player_pause = reinterpret_cast <plibvlcmediaplayerpause>(proc0);

	FARPROC proc2xy = GetProcAddress(avlc,"libvlc_audio_set_volume");
	if(proc2xy == NULL ){
		ShowMessage("getting libvlc_autio_set_volume is failed");
	}

	libvlc_audio_set_volume = reinterpret_cast <plibvlc_audio_set_volume>(proc2xy);


	FARPROC proc = GetProcAddress(avlc,"libvlc_new");
	if(proc == NULL ){
		ShowMessage("getting libvlc_new is failed");
	}

	libvlc_new = reinterpret_cast <plibvlcnew>(proc);

	FARPROC proc2 = GetProcAddress(avlc,"libvlc_media_new_location");
		if(proc2 == NULL ){
		ShowMessage("getting libvlc_media_new_location is failed");
	}

	libvlc_media_new_location = reinterpret_cast <plibvlcmedianewlocation>(proc2);

	FARPROC proc3 = GetProcAddress(avlc,"libvlc_media_player_new_from_media");
		if(proc3 == NULL ){
		ShowMessage("getting libvlc_player_new_from_media is failed");
	}

	libvlc_media_player_new_from_media = reinterpret_cast <plibvlcmediaplayernewfrommedia>(proc3);


	FARPROC proc4 = GetProcAddress(avlc,"libvlc_media_release");
		if( proc4  == NULL ){
		ShowMessage("getting libvlc_media_release is failed");
	}

	libvlc_media_release = reinterpret_cast <plibvlcmediarelease>(proc4);

	FARPROC proc5 = GetProcAddress(avlc,"libvlc_video_set_scale");
		if(proc5 == NULL ){
		ShowMessage("getting libvlc_video_set_scale is failed");
	}

	libvlc_video_set_scale = reinterpret_cast <plibvlcvideosetscale>(proc5);

	FARPROC proc6 = GetProcAddress(avlc,"libvlc_media_player_play");
		if(proc6 == NULL ){
		ShowMessage("getting libvlc_media_player_play is failed");
	}

	libvlc_media_player_play = reinterpret_cast <plibvlcmediaplayerplay>(proc6);


	FARPROC proc7 = GetProcAddress(avlc,"libvlc_media_add_option");

	if(proc7 == NULL ){
		ShowMessage("getting libvlc_media_add_option is failed");
	}

	libvlc_media_add_option = reinterpret_cast <plibvlcmediaaddoption>(proc7);

	FARPROC proc8 = GetProcAddress(avlc,"libvlc_media_add_option");

	if(proc8 == NULL ){
		ShowMessage("getting libvlc_media_player_is_playing is failed");
	}

	libvlc_media_player_is_playing = reinterpret_cast <plibvlcmediaplayerisplaying>(proc8);


	FARPROC proc9 = GetProcAddress(avlc,"libvlc_media_player_set_hwnd");

	if(proc9 == NULL ){
		ShowMessage("getting libvlc_media_player_set_hwnd is failed");
	}

	libvlc_media_player_set_hwnd = reinterpret_cast <plibvlcmediaplayersethwnd>(proc9);



		FARPROC proc10 = GetProcAddress(avlc,"libvlc_media_player_stop");

	if(proc10 == NULL ){
		ShowMessage("getting libvlc_media_player_stop is failed");
	}

	libvlc_media_player_stop = reinterpret_cast <plibvlcmediaplayerstop>(proc10);

	FARPROC proc11 = GetProcAddress(avlc,"libvlc_media_player_release");

	if(proc11 == NULL ){
		ShowMessage("getting libvlc_media_player_release is failed");
	}

	libvlc_media_player_release = reinterpret_cast <plibvlcmediaplayerrelease>(proc11);

		FARPROC proc12 = GetProcAddress(avlc,"libvlc_release");

	if(proc12 == NULL ){
		ShowMessage("getting libvlc_release is failed");
	}

	libvlc_release = reinterpret_cast <plibvlcrelease>(proc12);




	FARPROC proc13 = GetProcAddress(avlc,"libvlc_video_take_snapshot");

	if(proc13 == NULL ){
		ShowMessage("getting libvlc_video_take_snapshot is failed");
	}

	libvlc_video_take_snapshot = reinterpret_cast <plibvlcvideotakesnapshot>(proc13);


	}


	public:


	VLC(AnsiString location){

		initaddress();
		instance = libvlc_new(0, NULL);

		VlcMedia =  libvlc_media_new_location(instance,location.c_str());
		media_player = libvlc_media_player_new_from_media(VlcMedia);
		libvlc_media_release(VlcMedia);
	}

	void SetHWND(HWND Handle){
		 libvlc_media_player_set_hwnd(media_player,Handle);
	}

	void Option(AnsiString option){

		libvlc_media_add_option(VlcMedia,option.c_str());

	}
	void Play(void){
		 libvlc_media_player_play(media_player);
	}

	void Pause(void){
		libvlc_media_player_pause(media_player);
	}
	void Stop(void){

       	if(!media_player)
			return;

		libvlc_media_player_stop(media_player);

		libvlc_media_player_release(media_player);



		libvlc_release(instance);
	}

	void SetVolume(int vol){
		libvlc_audio_set_volume(media_player,vol);

	}

	int SnapShot(AnsiString fname){
		int ret;

		ret = libvlc_video_take_snapshot(media_player,0,fname.c_str(),0,0);
		return ret;
	}

};

#endif

引数並びを間違えずに宣言して、

	typedef int WINAPI (*plibvlcvideotakesnapshot)(libvlc_media_player_t *,int,const char*,int,int);
	plibvlcvideotakesnapshot libvlc_video_take_snapshot;
	FARPROC proc13 = GetProcAddress(avlc,"libvlc_video_take_snapshot");

	if(proc13 == NULL ){
		ShowMessage("getting libvlc_video_take_snapshot is failed");
	}

	libvlc_video_take_snapshot = reinterpret_cast <plibvlcvideotakesnapshot>(proc13);

が追加分です。aspect ratioの設定も関数呼び出しでできますが、面倒なのでオプション文字列で設定しています。本当はUnit1.cppの末尾のコメント部分内部のように、デバイス名、スクリーン分解能(横x縦)、アスペクト比を設定すべきですが、面倒なのでデフォルトで…..。さて起動すると、

ここで“Still”ボタンをクリックすると、ファイルセーブされます。アスペクト比が間違っていると、左右に黒い部分がでてきます。

ファイルは、

live画像のスナップショットなので、寸分違いませんね。たまたま横に映り込んでいるのが、EZVIZ CS-CP1ですが、こちらで静止画撮る(といっても動画キャプチャー中のスクリーンダンプ経由)と、

この距離だとこの画像で、歪みが大きくて認識率低くなりそうなので使いません。現時点で、APIわからないしね。

ライブカメラからの静止画も撮れるようになりましたから、最終目標に向かってじわじわ進んでいます。

コメント