« It's ... | トップページ | そういえば… »

2008年8月 8日 (金)

OpenGLで動画

OpenGLの実行画面をキャプチャーしてビデオを作成したいなぁ~と思って,プログラム組んでみたのですが,やっぱりglReadPixels()を使っているせいか,録画最中はかなりフレームレートが下がって使いもんにならなそうです。

なんか,うまいやり方ありそうなんですけどね…全然わかりません。

あんまし,いい結果にならないので,ホームページではなく,ここで一応要の部分のコードを公開しておこうかなって思います。

<< AviCreator.h >>

#ifndef __AVI_CREATOR_H_INCLUDED__
#define __AVI_CREATOR_H_INCLUDED__

//
// Includes
//
#include <windows.h>
#include <vfw.h>
#include <GL/glew.h>
#include <GL/glut.h>

//
// Link
//
#pragma comment(lib, "vfw32.lib")
#pragma comment(lib, "glew32.lib")

//
// CAviCreator class
//
class CAviCreator
{
protected:
unsigned int m_Width;
unsigned int m_Height;
unsigned long m_Size;
unsigned long m_Scale;
unsigned long m_Rate;
GLubyte* m_Pixels;
unsigned long m_FrameCount;
AVISTREAMINFOA m_AviStreamInfo;
PAVIFILE m_pAviFile;
PAVISTREAM m_pAviStream;
GLuint m_PboID[2];

public:
CAviCreator();
~CAviCreator();

bool Start( unsigned int width, unsigned int height, const char *file, unsigned long scale, unsigned long rate );
bool CaptureWindow();
void End();
void Release();
};

#endif // __AVI_CREATOR_H_INCLUDED__

<< AviCreator.cpp >>

//
// Includs
//
#include "AviCreator.h"

/////////////////////////////////////////////////////////////////////////
// CAviCreator class
/////////////////////////////////////////////////////////////////////////

//----------------------------------------------------------------------------------------------------
// Name : CAviCreator()
// Desc : コンストラクタ
//----------------------------------------------------------------------------------------------------
CAviCreator::CAviCreator()
{
m_Width = 0;
m_Height = 0;
m_Scale = 0;
m_Rate = 0;
m_Size = 0;
m_Pixels = NULL;
m_FrameCount = 0;
m_PboID[0] = 0;
m_PboID[1] = 0;
}

//----------------------------------------------------------------------------------------------------
// Name : ~CAviCreator()
// Desc : デストラクタ
//----------------------------------------------------------------------------------------------------
CAviCreator::~CAviCreator()
{
Release();
}

//----------------------------------------------------------------------------------------------------
// Name : Release()
// Desc : 後片付け
//----------------------------------------------------------------------------------------------------
void CAviCreator::Release()
{
// PBOの破棄
if ( m_PboID[0] != 0 )
{
  glDeleteBuffers( 1, &m_PboID[0] );
  m_PboID[0] = 0;
}
if ( m_PboID[1] != 0 )
{
  glDeleteBuffers( 1, &m_PboID[1] );
  m_PboID[1] = 0;
}

m_Width = 0;
m_Height = 0;
m_Scale = 0;
m_Rate = 0;
m_Size = 0;
m_Pixels = NULL;
m_FrameCount = 0;
}

//----------------------------------------------------------------------------------------------------
// Name : Start()
// Desc : セットアップをして録画を開始
//----------------------------------------------------------------------------------------------------
bool CAviCreator::Start(unsigned int width, unsigned int height, const char *file, unsigned long scale, unsigned long rate)
{
// GLEWの初期化
if ( glewInit() != GLEW_OK )
{
  MessageBox( NULL, TEXT("Error : GLEWの初期化に失敗しました"), TEXT("Error !!"), MB_ICONERROR | MB_OK );
  return false;
}

// 変数代入
m_Width = width;
m_Height = height;
m_Scale = scale;
m_Rate = rate;
m_FrameCount = 0;
m_Size = 0;

// サイズ決定
m_Size = (((m_Width*24+31)&~31 )/8) * m_Height;

// 設定
BITMAPINFOHEADER bmih = { sizeof(BITMAPINFOHEADER), m_Width, m_Height, 1, 24, BI_RGB, m_Size, 0, 0, 0, 0 };
AVISTREAMINFOA si = { streamtypeVIDEO, comptypeDIB, 0, 0, 0, 0, m_Scale, m_Rate, 0, 0, 0, 0, (DWORD)-1, 0, { 0, 0, m_Width, m_Height }, 0, 0, "VIDEO" };
m_AviStreamInfo = si;

// AVIファイルの初期化
AVIFileInit();

// ファイルオープン
if ( AVIFileOpenA( &m_pAviFile, file, OF_CREATE | OF_WRITE | OF_SHARE_DENY_NONE, NULL ) != 0 )
{
  MessageBox( NULL, TEXT("Error : ファイルが開けませんでした"), TEXT("Error !!"), MB_ICONERROR | MB_OK );
  return false;
}

// ストリーム作成
if ( AVIFileCreateStreamA( m_pAviFile, &m_pAviStream, &m_AviStreamInfo ) != 0 )
{
  MessageBox( NULL, TEXT("Error : 編集用ファイルストリームの作成に失敗しました"), TEXT("Error !!"), MB_ICONERROR | MB_OK );
  return false;
}

// フォーマットをセット
if ( AVIStreamSetFormat( m_pAviStream, 0, &bmih, sizeof(BITMAPINFOHEADER) ) != 0 )
{
  MessageBox( NULL, TEXT("Error : ストリームのフォーマット設定に失敗しました"), TEXT("Error !!"), MB_ICONERROR | MB_OK );
  return false;
}

// PBOを作成
glGenBuffers( 2, m_PboID );
glBindBuffer( GL_PIXEL_PACK_BUFFER, m_PboID[0] );
glBufferData( GL_PIXEL_PACK_BUFFER, m_Size, 0, GL_STREAM_READ );
glBindBuffer( GL_PIXEL_PACK_BUFFER, m_PboID[1] );
glBufferData( GL_PIXEL_PACK_BUFFER, m_Size, 0, GL_STREAM_READ );
glBindBuffer( GL_PIXEL_PACK_BUFFER, 0 );

return true;
}

//----------------------------------------------------------------------------------------------------
// Name : CaptureWindow()
// Desc : 描画結果をキャプチャーしてフレームに書き込み
//----------------------------------------------------------------------------------------------------
bool CAviCreator::CaptureWindow()
{
static int index = 0;
static int nextIndex = 0;

// インデックス決定
index = (index + 1) %2;
nextIndex = (index + 1) %2;

// ピクセルデータの読み取り
glBindBuffer( GL_PIXEL_PACK_BUFFER, m_PboID[index] );
glReadPixels( 0, 0, m_Width, m_Height, GL_BGR, GL_UNSIGNED_BYTE, 0 );
glBindBuffer( GL_PIXEL_PACK_BUFFER, m_PboID[nextIndex] );
m_Pixels = (GLubyte*)glMapBuffer( GL_PIXEL_PACK_BUFFER, GL_READ_ONLY );

// ファイルに書き込み
if ( AVIStreamWrite( m_pAviStream, m_FrameCount++, 1, m_Pixels, m_Size, AVIIF_KEYFRAME, NULL, NULL ) )
{
  return false;
}

// バインドを戻す
glUnmapBuffer( GL_PIXEL_PACK_BUFFER );
glBindBuffer( GL_PIXEL_PACK_BUFFER, 0 );

return true;
}

//----------------------------------------------------------------------------------------------------
// Name : End()
// Desc : ファイル作成終了
//----------------------------------------------------------------------------------------------------
void CAviCreator::End()
{
// ストリームを破棄
AVIStreamRelease( m_pAviStream );

// ファイルを破棄
AVIFileRelease( m_pAviFile );

// ファイル作成終了
AVIFileExit();

// 後片付け
Release();

//
MessageBox( NULL, TEXT("AVIファイルの作成に成功しました"), TEXT("ファイル作成完了"), MB_ICONINFORMATION | MB_OK );
}

« It's ... | トップページ | そういえば… »

コメント

この記事へのコメントは終了しました。

トラックバック


この記事へのトラックバック一覧です: OpenGLで動画:

« It's ... | トップページ | そういえば… »