LosaDev source snapshot 2019

This commit is contained in:
LosaDev committed 2026-11-07 13:30:45 +07:00
commit c198676e97
20588 files changed
+8812878

No files matched your search

@@ -0,0 +1,147 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// BandiVideoLibrary 2.1
///
/// Copyright(C) 2008-2011 BandiSoft.com All rights reserved.
///
/// Visit http://www.bandisoft.com for more information.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#include "BandiVideoFileReader.h"
CBandiVideoFileReader::CBandiVideoFileReader() : m_ref_count(0), m_file_handle(NULL)
{
}
CBandiVideoFileReader::~CBandiVideoFileReader()
{
Close();
}
STDMETHODIMP_(ULONG) CBandiVideoFileReader::AddRef()
{
LONG lRef = InterlockedIncrement(&m_ref_count);
ASSERT(lRef >= 0);
return m_ref_count;
}
STDMETHODIMP_(ULONG) CBandiVideoFileReader::Release()
{
LONG lRef = InterlockedDecrement(&m_ref_count);
ASSERT(lRef >= 0);
if(lRef == 0)
{
delete this;
return ULONG(0);
}
return m_ref_count;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Open a bandivideo file.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoFileReader::Open(LPCWSTR path_name)
{
Close();
HANDLE hFile = CreateFileW(path_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(hFile == INVALID_HANDLE_VALUE)
return E_FAIL;
m_file_handle = hFile;
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Close a bandivideo file.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
void CBandiVideoFileReader::Close()
{
if(m_file_handle)
{
::CloseHandle(m_file_handle);
m_file_handle = NULL;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Read data from a file.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
INT CBandiVideoFileReader::Read(BYTE* buf, INT bytes_to_read)
{
DWORD dwBytesRead = 0;
if (!::ReadFile(m_file_handle, buf, bytes_to_read, &dwBytesRead, NULL))
return 0;
return dwBytesRead;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Move the file pointer of the specified file.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
INT64 CBandiVideoFileReader::SetPosition(INT64 pos)
{
LARGE_INTEGER li;
li.QuadPart = pos;
li.LowPart = ::SetFilePointer(m_file_handle , li.LowPart , &li.HighPart , FILE_BEGIN);
if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
{
li.QuadPart = -1;
}
return li.QuadPart;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Return the file pointer of the specified file.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
INT64 CBandiVideoFileReader::GetPosition()
{
LARGE_INTEGER li;
li.QuadPart = 0;
li.LowPart = ::SetFilePointer(m_file_handle , li.LowPart , &li.HighPart , FILE_CURRENT);
return li.QuadPart;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Return the size of the specified file.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
INT64 CBandiVideoFileReader::GetFileSize()
{
LARGE_INTEGER size = {0, 0};
size.LowPart = ::GetFileSize(m_file_handle , (DWORD*)&size.HighPart);
return size.QuadPart;
}
@@ -0,0 +1,38 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// BandiVideoLibrary 2.1
///
/// Copyright(C) 2008-2011 BandiSoft.com All rights reserved.
///
/// Visit http://www.bandisoft.com for more information.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "bandivid.h"
class CBandiVideoFileReader : public IBandiVideoFileReader
{
public:
CBandiVideoFileReader();
virtual ~CBandiVideoFileReader();
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { return E_NOTIMPL; };
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IBandiVideoFileReader
HRESULT Open(LPCWSTR path_name);
void Close();
INT Read(BYTE* buf, INT bytes_to_read);
INT64 SetPosition(INT64 pos);
INT64 GetPosition();
INT64 GetFileSize();
protected:
LONG m_ref_count;
HANDLE m_file_handle;
};
@@ -0,0 +1,172 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// BandiVideoLibrary 2.1
///
/// Copyright(C) 2008-2011 BandiSoft.com All rights reserved.
///
/// Visit http://www.bandisoft.com for more information.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#include "BandiVideoLibrary.h"
CBandiVideoLibrary::CBandiVideoLibrary()
{
m_dll = NULL;
m_pCreateBandiVideo2 = NULL;
m_bvl = NULL;
}
CBandiVideoLibrary::~CBandiVideoLibrary()
{
Destroy();
}
// 라이브러리 초기화
HRESULT CBandiVideoLibrary::Create(LPCTSTR dll_path_name, IBandiVideoFileReader *reader /*= NULL */, IBandiVideoSound *sound /*= NULL */)
{
if(m_dll) {ASSERT(0); return BVERR_ALREADY_CREATED;}
// check os version
OSVERSIONINFO osv;
osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&osv)==FALSE ||
osv.dwPlatformId <=VER_PLATFORM_WIN32_WINDOWS) // does not support 98
{
return BVERR_UNSUPPORTED_OS;
}
// DLL 로드
m_dll = LoadLibrary(dll_path_name);
if(m_dll==NULL)
{
m_dll = LoadLibrary(BANDIVIDEO_RELEASE_DLL_FILE_NAME);
if(m_dll==NULL)
{
ASSERT(0);
return BVERR_LOAD_LIBRARY_FAIL;
}
}
m_pCreateBandiVideo2 = (LPCREATEBANDIVIDEO2)GetProcAddress(m_dll, "CreateBandiVideo2");
if(m_pCreateBandiVideo2==NULL)
{
ASSERT(0);
FreeLibrary(m_dll);
m_dll = NULL;
return BVERR_GET_PROC_ADDRESS_FAIL;
}
return m_pCreateBandiVideo2(BVL_VERSION, (void**)&m_bvl, reader, sound);
}
BOOL CBandiVideoLibrary::IsCreated()
{
return m_bvl ? TRUE : FALSE;
}
// 라이브러리 해제
void CBandiVideoLibrary::Destroy()
{
if(m_bvl)
{
m_bvl->Release();
m_bvl = NULL;
}
m_pCreateBandiVideo2 = NULL;
if(m_dll) FreeLibrary(m_dll);
m_dll = NULL;
}
// 인증하기
HRESULT CBandiVideoLibrary::Verify(LPCSTR id, LPCSTR key)
{
if(m_bvl==NULL) {ASSERT(0); return BVERR_LIBRARY_NOT_LOADED;}
return m_bvl->Verify(id, key);
}
// 버전 정보
INT CBandiVideoLibrary::GetVersion()
{
if(m_bvl==NULL) {ASSERT(0); return 0;}
return m_bvl->GetVersion();
}
HRESULT CBandiVideoLibrary::Open(LPCWSTR path_name, BOOL async)
{
if(m_bvl==NULL) {ASSERT(0); return BVERR_LIBRARY_NOT_LOADED;}
return m_bvl->Open(path_name, async);
}
HRESULT CBandiVideoLibrary::Open(LPCSTR path_name, BOOL async)
{
if(m_bvl==NULL) {ASSERT(0); return BVERR_LIBRARY_NOT_LOADED;}
WCHAR wszPath[MAX_PATH+1];
MultiByteToWideChar(CP_ACP, NULL, path_name, -1, wszPath, MAX_PATH);
return m_bvl->Open(wszPath, async);
}
HRESULT CBandiVideoLibrary::Close()
{
if(m_bvl==NULL) {ASSERT(0); return BVERR_LIBRARY_NOT_LOADED;}
return m_bvl->Close();
}
HRESULT CBandiVideoLibrary::Play()
{
if(m_bvl==NULL) {ASSERT(0); return BVERR_LIBRARY_NOT_LOADED;}
return m_bvl->Play();
}
HRESULT CBandiVideoLibrary::Stop()
{
if(m_bvl==NULL) {ASSERT(0); return BVERR_LIBRARY_NOT_LOADED;}
return m_bvl->Stop();
}
HRESULT CBandiVideoLibrary::Seek(INT64 value, BVL_SEEK_FLAG seek_flag)
{
if(m_bvl==NULL) {ASSERT(0); return BVERR_LIBRARY_NOT_LOADED;}
return m_bvl->Seek(value, seek_flag);
}
HRESULT CBandiVideoLibrary::Pause(BOOL pause)
{
if(m_bvl==NULL) {ASSERT(0); return BVERR_LIBRARY_NOT_LOADED;}
return m_bvl->Pause(pause);
}
BOOL CBandiVideoLibrary::IsNextFrame()
{
if(m_bvl==NULL) {ASSERT(0); return FALSE;}
return m_bvl->IsNextFrame();
}
HRESULT CBandiVideoLibrary::GetFrame(BVL_FRAME &frame, BOOL can_skip)
{
if(m_bvl==NULL) {ASSERT(0); return BVERR_LIBRARY_NOT_LOADED;}
return m_bvl->GetFrame(frame, can_skip);
}
HRESULT CBandiVideoLibrary::GetVideoInfo(BVL_VIDEO_INFO &info)
{
if(m_bvl==NULL) {ASSERT(0); return BVERR_LIBRARY_NOT_LOADED;}
return m_bvl->GetVideoInfo(info);
}
HRESULT CBandiVideoLibrary::GetStatus(BVL_STATUS &status)
{
if(m_bvl==NULL) {ASSERT(0); return BVERR_LIBRARY_NOT_LOADED;}
return m_bvl->GetStatus(status);
}
HRESULT CBandiVideoLibrary::SetVolume(INT volume)
{
if(m_bvl==NULL) {ASSERT(0); return BVERR_LIBRARY_NOT_LOADED;}
return m_bvl->SetVolume(volume);
}
@@ -0,0 +1,77 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// BandiVideoLibrary 2.1
///
/// Copyright(C) 2008-2011 BandiSoft.com All rights reserved.
///
/// Visit http://www.bandisoft.com for more information.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "bandivid.h"
#ifdef _WIN64
# ifdef _DEBUG
# define BANDIVIDEO_DLL_FILE_NAME _T("bdvid64_d.dll")
# else
# define BANDIVIDEO_DLL_FILE_NAME _T("bdvid64.dll")
# endif
# define BANDIVIDEO_RELEASE_DLL_FILE_NAME _T("bdvid64.dll")
#else
# ifdef _DEBUG
# define BANDIVIDEO_DLL_FILE_NAME _T("bdvid32_d.dll")
# else
# define BANDIVIDEO_DLL_FILE_NAME _T("bdvid32.dll")
# endif
# define BANDIVIDEO_RELEASE_DLL_FILE_NAME _T("bdvid32.dll")
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
// utility class for load library and create instance for video library
////////////////////////////////////////////////////////////////////////////////////////////////////
class CBandiVideoLibrary : public IBandiVideo2
{
public :
CBandiVideoLibrary();
~CBandiVideoLibrary();
HRESULT Create(LPCTSTR dll_path_name, IBandiVideoFileReader *reader = NULL, IBandiVideoSound *sound = NULL);
void Destroy();
BOOL IsCreated();
public :
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** p) { return E_NOTIMPL; }
ULONG STDMETHODCALLTYPE AddRef(void) {return 0;}
ULONG STDMETHODCALLTYPE Release(void) {return 0;}
// IBandiVideo2
HRESULT Verify(LPCSTR szID, LPCSTR szKey); // ÀÎÁõÇϱâ
INT GetVersion(); // ¹öÀü Á¤º¸
HRESULT Open(LPCWSTR path_name, BOOL async = FALSE);
HRESULT Open(LPCSTR path_name, BOOL async = FALSE);
HRESULT Close();
HRESULT Play();
HRESULT Stop();
HRESULT Seek(INT64 value, BVL_SEEK_FLAG seek_flag);
HRESULT Pause(BOOL pause);
BOOL IsNextFrame();
HRESULT GetFrame(BVL_FRAME &frame, BOOL can_skip);
HRESULT GetVideoInfo(BVL_VIDEO_INFO &info);
HRESULT GetStatus(BVL_STATUS &status);
HRESULT SetVolume(INT volume); // 0 ~ 255
private :
HMODULE m_dll;
LPCREATEBANDIVIDEO2 m_pCreateBandiVideo2;
public:
IBandiVideo2* m_bvl;
};
@@ -0,0 +1,504 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// BandiVideoLibrary 2.1
///
/// Copyright(C) 2008-2011 BandiSoft.com All rights reserved.
///
/// Visit http://www.bandisoft.com for more information.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <process.h>
#include <math.h>
#include "BandiVideoSound_DS.h"
#define BVL_DSWND_CLASS_NAME _T("CBandiVideoSound_DS")
CBandiVideoSound_DS::CBandiVideoSound_DS() : m_ref_count(0)
{
m_hwnd = NULL;
m_hinst = NULL;
m_ds = NULL;
m_dsb_primary = NULL;
m_dsb_secondary = NULL;
m_channels = m_samplerate = 0;
m_last_write_pos = 0;
m_inbuf_samples = m_total_samples = 0;
m_cur_play_time = 0;
memset(&m_crit_sec, NULL, sizeof(m_crit_sec));
m_crit_sec_inited = FALSE;
m_hevent = NULL;
m_hthread = NULL;
m_thread_id = 0;
m_playing = FALSE;
m_callback = NULL;
m_outbuf_size_max = -1;
m_outbuf_size_min = -1;
memset(m_sample_block, NULL, PLAY_SAMPLE_BLOCK_LEN);
m_sample_block_size = 0;
}
CBandiVideoSound_DS::~CBandiVideoSound_DS()
{
Close();
}
STDMETHODIMP_(ULONG) CBandiVideoSound_DS::AddRef()
{
LONG lRef = InterlockedIncrement(&m_ref_count);
ASSERT(lRef >= 0);
return m_ref_count;
}
STDMETHODIMP_(ULONG) CBandiVideoSound_DS::Release()
{
LONG lRef = InterlockedDecrement(&m_ref_count);
ASSERT(lRef >= 0);
if(lRef == 0)
{
delete this;
return ULONG(0);
}
return m_ref_count;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Open sound device.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_DS::Open(INT channels, INT samplerate, IBandiVideoSoundCB *callback)
{
Close();
HRESULT hr = E_FAIL;
m_hinst = (HINSTANCE)GetModuleHandle(NULL);
if(m_hinst == NULL) goto error;
WNDCLASS wc;
ZeroMemory(&wc, sizeof(wc));
wc.lpfnWndProc = DefWindowProc;
wc.lpszClassName = BVL_DSWND_CLASS_NAME;
RegisterClass(&wc);
// 버퍼타임으로 버퍼 byte 크기 계산
m_outbuf_size_max = MulDiv(samplerate * channels * 2, MAX_BUFFER_TIME , 1000) ;
m_outbuf_size_min = MulDiv(samplerate * channels * 2, MIN_BUFFER_TIME ,1000 );
// Create dummy window
m_hwnd = CreateWindow(BVL_DSWND_CLASS_NAME, _T(""), 0, 0, 0, 0, 0, NULL, NULL, m_hinst, 0L);
if(m_hwnd == NULL)
goto error;
// Create Direct Sound Instance
hr = DirectSoundCreate8(NULL, &m_ds, NULL);
if(FAILED(hr))
goto error;
hr = m_ds->SetCooperativeLevel(m_hwnd, DSSCL_PRIORITY);
if(FAILED(hr))
goto error;
// Create a primary buffer
DSBUFFERDESC dsbdesc;
ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
hr = m_ds->CreateSoundBuffer(&dsbdesc, &m_dsb_primary, NULL);
if(FAILED(hr))
goto error;
// Set format of the primary buffer
WAVEFORMATEX wfx;
ZeroMemory(&wfx, sizeof(WAVEFORMATEX));
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = channels;
wfx.nSamplesPerSec = samplerate;
wfx.wBitsPerSample = 16;
wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
hr = m_dsb_primary->SetFormat(&wfx);
if(FAILED(hr))
goto error;
// Create secondary sound buffer
ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS
/*| DSBCAPS_LOCDEFER | DSBCAPS_CTRLFREQUENCY*/ | DSBCAPS_CTRLVOLUME;
dsbdesc.dwBufferBytes = m_outbuf_size_max;
dsbdesc.lpwfxFormat = &wfx;
hr = m_ds->CreateSoundBuffer(&dsbdesc, &m_dsb_secondary, NULL);
if(FAILED(hr))
goto error;
InitializeCriticalSection(&m_crit_sec);
m_crit_sec_inited = TRUE;
// Create an event object for periodical processing
m_hevent = CreateEvent(NULL, FALSE, FALSE, NULL); // auto reset event
if(m_hevent == NULL)
goto error;
// Create thread for playback
m_hthread = (HANDLE)_beginthreadex(NULL, 0, InitialThreadProc, this, CREATE_SUSPENDED, &m_thread_id);
if(m_hthread == NULL)
goto error;
m_channels = channels;
m_samplerate = samplerate;
m_callback = callback;
memset(m_sample_block, NULL, PLAY_SAMPLE_BLOCK_LEN);
m_sample_block_size = 0;
SetThreadPriority(m_hthread, THREAD_PRIORITY_TIME_CRITICAL);
ResumeThread(m_hthread);
return S_OK;
error:
Close();
return FAILED(hr) ? hr : E_FAIL;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Close sound device.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
void CBandiVideoSound_DS::Close()
{
HANDLE hThread = (HANDLE)InterlockedExchangePointer(&m_hthread, 0);
if(hThread)
{
if(m_hevent) SetEvent(m_hevent);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
if(m_hevent)
{
CloseHandle(m_hevent);
m_hevent = NULL;
}
if(m_crit_sec_inited)
{
DeleteCriticalSection(&m_crit_sec);
m_crit_sec_inited = FALSE;
}
if(m_dsb_secondary)
{
m_dsb_secondary->Release();
m_dsb_secondary = NULL;
}
if(m_dsb_primary)
{
m_dsb_primary->Release();
m_dsb_primary = NULL;
}
if(m_ds)
{
m_ds->Release();
m_ds = NULL;
}
if(m_hwnd)
{
DestroyWindow(m_hwnd);
UnregisterClass(BVL_DSWND_CLASS_NAME, m_hinst);
m_hwnd = NULL;
}
m_channels = m_samplerate = 0;
m_last_write_pos = 0;
m_inbuf_samples = m_total_samples = 0;
m_cur_play_time = 0;
m_playing = FALSE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Start
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_DS::Start()
{
EnterCriticalSection(&m_crit_sec);
m_playing = TRUE;
LeaveCriticalSection(&m_crit_sec);
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Stop
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_DS::Stop()
{
EnterCriticalSection(&m_crit_sec);
m_playing = FALSE;
if(m_dsb_secondary)
{
BYTE *pbData = NULL;
BYTE *pbData2 = NULL;
DWORD dwLength=0;
DWORD dwLength2=0;
m_dsb_secondary->Stop();
m_dsb_secondary->SetCurrentPosition(0);
// Lock DirectSound buffer
m_dsb_secondary->Lock(0, m_outbuf_size_max, (void**)&pbData, &dwLength, (void**)&pbData2, &dwLength2, 0);
if(pbData) memset(pbData, 0, dwLength);
if(pbData2) memset(pbData2, 0, dwLength2);
// Unlock the buffer
m_dsb_secondary->Unlock(pbData, dwLength, pbData2, dwLength2);
m_last_write_pos = 0;
m_total_samples = m_inbuf_samples = 0;
m_cur_play_time = 0;
memset(m_sample_block, NULL, PLAY_SAMPLE_BLOCK_LEN);
m_sample_block_size = 0;
}
LeaveCriticalSection(&m_crit_sec);
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Stop
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_DS::Pause(BOOL pause)
{
EnterCriticalSection(&m_crit_sec);
if(pause)
{
m_playing = FALSE;
if(m_dsb_secondary) m_dsb_secondary->Stop();
}
else
{
m_playing = TRUE;
}
LeaveCriticalSection(&m_crit_sec);
return S_OK;
}
#include <stdio.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Get play time (100nsec units)
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_DS::GetTime(INT64 &time)
{
EnterCriticalSection(&m_crit_sec);
time = m_cur_play_time;
LeaveCriticalSection(&m_crit_sec);
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Set sound volume
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_DS::SetVolume(INT volume)
{
if(m_dsb_secondary == NULL)
return E_POINTER;
double lfPower10 = pow(10.0,-10.0); // 10^(-10);
double lfVolume = (1 - lfPower10)*((double)volume/255) + lfPower10;
lfVolume = 10*log10(lfVolume);
lfVolume *= 300;
if(lfVolume < -10000)
lfVolume = -10000;
return m_dsb_secondary->SetVolume((LONG)lfVolume);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// ThreadProc
///
////////////////////////////////////////////////////////////////////////////////////////////////////
UINT CBandiVideoSound_DS::ThreadProc()
{
BOOL bWorking = FALSE;
while(m_hthread)
{
EnterCriticalSection(&m_crit_sec);
{
if(m_playing)
PlayDS();
}
LeaveCriticalSection(&m_crit_sec);
WaitForSingleObject(m_hevent, 2);
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Play DirectSound
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_DS::PlayDS()
{
HRESULT hr;
int sample_bytes = m_channels*sizeof(INT16);
DWORD free_buffer_size = GetFreeBufferSize();
// Update play position
m_inbuf_samples = (m_outbuf_size_max - free_buffer_size)/(m_channels*sizeof(INT16));
m_cur_play_time = max((m_total_samples - m_inbuf_samples)*10000000i64/m_samplerate, 0);
// Transfer PCM data to Direct Sound Buffer
if(m_callback)
{
void *lock1_ptr = NULL;
void *lock2_ptr = NULL;
DWORD lock1_bytes = 0;
DWORD lock2_bytes = 0;
if(m_sample_block_size < PLAY_SAMPLE_BLOCK_LEN)
{
int req_samples = (PLAY_SAMPLE_BLOCK_LEN-m_sample_block_size)/sample_bytes;
int get_samples = m_callback->GetPcmData((INT16*)(&m_sample_block[m_sample_block_size]), req_samples);
m_sample_block_size += get_samples*sample_bytes;
}
if(m_sample_block_size == PLAY_SAMPLE_BLOCK_LEN && m_sample_block_size <= free_buffer_size)
{
hr = m_dsb_secondary->Lock(m_last_write_pos, m_sample_block_size,
&lock1_ptr, &lock1_bytes,
&lock2_ptr, &lock2_bytes, 0);
if(hr == DSERR_BUFFERLOST)
{
m_dsb_secondary->Restore();
hr = m_dsb_secondary->Lock(m_last_write_pos, m_sample_block_size,
&lock1_ptr, &lock1_bytes,
&lock2_ptr, &lock2_bytes, 0);
}
if(FAILED(hr)) return hr;
if(lock1_ptr) memcpy(lock1_ptr, m_sample_block, lock1_bytes);
if(lock2_ptr) memcpy(lock2_ptr, m_sample_block+lock1_bytes, lock2_bytes);
m_dsb_secondary->Unlock(lock1_ptr, lock1_bytes, lock2_ptr, lock2_bytes);
// Update Write Pointer
m_total_samples += m_sample_block_size/sample_bytes;
m_last_write_pos += m_sample_block_size;
if (INT(m_last_write_pos) >= m_outbuf_size_max)
m_last_write_pos = m_last_write_pos - m_outbuf_size_max;
m_sample_block_size = 0;
}
}
// PLAYBACK control
DWORD dsb_status;
m_dsb_secondary->GetStatus(&dsb_status);
if((dsb_status & DSBSTATUS_PLAYING) == 0)
{
if (m_inbuf_samples >= m_outbuf_size_min)
{
m_dsb_secondary->Play(0, 0, DSBPLAY_LOOPING);
}
}
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Get amount of free data in the buffer
///
////////////////////////////////////////////////////////////////////////////////////////////////////
DWORD CBandiVideoSound_DS::GetFreeBufferSize()
{
if(m_dsb_secondary == NULL) return 0;
if(m_total_samples == 0)
return m_outbuf_size_max;
DWORD play_pos;
DWORD free_buffer_size = 0;
if(SUCCEEDED(m_dsb_secondary->GetCurrentPosition(&play_pos, NULL)))
{
if(m_last_write_pos > play_pos)
free_buffer_size = (m_outbuf_size_max - m_last_write_pos) + play_pos;
else
free_buffer_size = play_pos - m_last_write_pos;
}
else
{
free_buffer_size = m_outbuf_size_max;
}
return free_buffer_size;
}
@@ -0,0 +1,89 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// BandiVideoLibrary 2.1
///
/// Copyright(C) 2008-2011 BandiSoft.com All rights reserved.
///
/// Visit http://www.bandisoft.com for more information.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#define DIRECTSOUND_VERSION 0x0800
#include <dsound.h>
#include "bandivid.h"
class CBandiVideoSound_DS : public IBandiVideoSound
{
public:
static const UINT MAX_BUFFER_TIME = 200; // ms
static const UINT MIN_BUFFER_TIME = 20; // ms
static const UINT PLAY_SAMPLE_BLOCK = 1000;
static const UINT PLAY_SAMPLE_BLOCK_LEN = PLAY_SAMPLE_BLOCK*4;
CBandiVideoSound_DS();
virtual ~CBandiVideoSound_DS();
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { return E_NOTIMPL; };
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IBandiVideoSound
HRESULT Open(INT channels, INT samplerate, IBandiVideoSoundCB *callback);
void Close();
HRESULT Start();
HRESULT Stop();
HRESULT Pause(BOOL pause);
HRESULT GetTime(INT64 &time);
HRESULT SetVolume(INT volume);
protected:
static unsigned WINAPI InitialThreadProc(LPVOID param)
{
CBandiVideoSound_DS *p = (CBandiVideoSound_DS*)param;
return p->ThreadProc();
};
UINT ThreadProc();
HRESULT PlayDS();
DWORD GetFreeBufferSize();
LONG m_ref_count;
HWND m_hwnd; // Window Handle
HINSTANCE m_hinst; // Instance Handle
LPDIRECTSOUND8 m_ds; // DirectSound Interface
LPDIRECTSOUNDBUFFER m_dsb_primary; // Primary buffer Interface
LPDIRECTSOUNDBUFFER m_dsb_secondary; // DirectSound secondary sound buffer
UINT m_channels; // Number of Channnel
UINT m_samplerate; // Sample rate;
INT m_outbuf_size_max;
INT m_outbuf_size_min;
UINT m_last_write_pos; // Last write offset (in BYTE)
INT m_inbuf_samples; // Number of samples in the buffer
INT m_total_samples; // Total number of written samples
LONGLONG m_cur_play_time; // 100nsec
CRITICAL_SECTION m_crit_sec;
BOOL m_crit_sec_inited;
HANDLE m_hevent;
HANDLE m_hthread;
UINT m_thread_id;
BOOL m_playing;
BYTE m_sample_block[PLAY_SAMPLE_BLOCK_LEN];
UINT m_sample_block_size;
IBandiVideoSoundCB* m_callback;
};
@@ -0,0 +1,294 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// BandiVideoLibrary 2.1
///
/// Copyright(C) 2008-2011 BandiSoft.com All rights reserved.
///
/// Visit http://www.bandisoft.com for more information.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#include <process.h>
#include "BandiVideoSound_NULL.h"
CBandiVideoSound_NULL::CBandiVideoSound_NULL() : m_ref_count(0)
{
m_init_count = 0;
m_start_time = 0;
memset(&m_crit_sec, NULL, sizeof(m_crit_sec));
m_crit_sec_inited = FALSE;
m_playing = FALSE;
m_hevent = NULL;
m_hthread = NULL;
m_thread_id = 0;
m_callback = NULL;
// Performance Frequency ±¸Çϱâ
LARGE_INTEGER freq = {0, 0};
QueryPerformanceFrequency(&freq);
m_freq_units = freq.QuadPart;
}
CBandiVideoSound_NULL::~CBandiVideoSound_NULL()
{
Close();
}
STDMETHODIMP_(ULONG) CBandiVideoSound_NULL::AddRef()
{
LONG lRef = InterlockedIncrement( &m_ref_count );
ASSERT(lRef >= 0);
return m_ref_count;
}
STDMETHODIMP_(ULONG) CBandiVideoSound_NULL::Release()
{
LONG lRef = InterlockedDecrement( &m_ref_count );
ASSERT(lRef >= 0);
if(lRef == 0)
{
delete this;
return ULONG(0);
}
return m_ref_count;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Open sound device.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::Open(INT channels, INT samplerate, IBandiVideoSoundCB *callback)
{
InitializeCriticalSection(&m_crit_sec);
m_crit_sec_inited = TRUE;
// Create an event object for periodical processing
m_hevent = CreateEvent(NULL, FALSE, FALSE, NULL); // auto reset event
if(m_hevent == NULL)
goto error;
// Create thread for playback
m_hthread = (HANDLE)_beginthreadex(NULL, 0, InitialThreadProc, this, CREATE_SUSPENDED, &m_thread_id);
if(m_hthread == NULL)
goto error;
m_callback = callback;
SetThreadPriority(m_hthread, THREAD_PRIORITY_TIME_CRITICAL);
ResumeThread(m_hthread);
return S_OK;
error:
Close();
return E_FAIL;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Close sound device.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
void CBandiVideoSound_NULL::Close()
{
HANDLE hThread = (HANDLE)InterlockedExchangePointer(&m_hthread, 0);
if(hThread)
{
if(m_hevent) SetEvent(m_hevent);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
if(m_hevent)
{
CloseHandle(m_hevent);
m_hevent = NULL;
}
if(m_crit_sec_inited)
{
DeleteCriticalSection(&m_crit_sec);
m_crit_sec_inited = FALSE;
}
m_init_count = 0;
m_start_time = 0;
}
static LONGLONG GetPerformanceCounter()
{
LARGE_INTEGER count;
::QueryPerformanceCounter(&count);
return count.QuadPart;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Start
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::Start()
{
EnterCriticalSection(&m_crit_sec);
{
m_init_count = GetPerformanceCounter();
m_start_time = 0;
m_playing = TRUE;
}
LeaveCriticalSection(&m_crit_sec);
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Stop
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::Stop()
{
EnterCriticalSection(&m_crit_sec);
{
m_start_time = 0;
m_playing = FALSE;
}
LeaveCriticalSection(&m_crit_sec);
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Stop
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::Pause(BOOL pause)
{
EnterCriticalSection(&m_crit_sec);
{
if(pause)
{
m_start_time = CalcTime();
m_playing = FALSE;
}
else
{
m_init_count = GetPerformanceCounter();
m_playing = TRUE;
}
}
LeaveCriticalSection(&m_crit_sec);
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Get play time (100nsec units)
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::GetTime(INT64 &time)
{
EnterCriticalSection(&m_crit_sec);
{
time = CalcTime();
}
LeaveCriticalSection(&m_crit_sec);
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Set sound volume
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::SetVolume(INT volume)
{
return E_NOTIMPL;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// ThreadProc
///
////////////////////////////////////////////////////////////////////////////////////////////////////
UINT CBandiVideoSound_NULL::ThreadProc()
{
BOOL bWorking = FALSE;
while(m_hthread)
{
EnterCriticalSection(&m_crit_sec);
{
if(m_playing)
PlayNULL();
}
LeaveCriticalSection(&m_crit_sec);
WaitForSingleObject(m_hevent, 10);
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Play NullSound
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoSound_NULL::PlayNULL()
{
if(m_callback)
{
INT16 buf[1024*2];
m_callback->GetPcmData(buf, 1024);
}
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Calculate current time
///
////////////////////////////////////////////////////////////////////////////////////////////////////
LONGLONG CBandiVideoSound_NULL::CalcTime()
{
LONGLONG ret;
LONGLONG delta_time = 0;
EnterCriticalSection(&m_crit_sec);
{
if(m_playing && m_freq_units)
delta_time = LONGLONG(double(GetPerformanceCounter() - m_init_count)/(double)m_freq_units*10000000.0);
ret = m_start_time + delta_time;
}
LeaveCriticalSection(&m_crit_sec);
return ret;
}
@@ -0,0 +1,62 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// BandiVideoLibrary 2.1
///
/// Copyright(C) 2008-2011 BandiSoft.com All rights reserved.
///
/// Visit http://www.bandisoft.com for more information.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "bandivid.h"
class CBandiVideoSound_NULL : public IBandiVideoSound
{
public:
CBandiVideoSound_NULL();
virtual ~CBandiVideoSound_NULL();
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppv) { return E_NOTIMPL; };
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// IBandiVideoSound
HRESULT Open(INT channels, INT samplerate, IBandiVideoSoundCB *callback);
void Close();
HRESULT Start();
HRESULT Stop();
HRESULT Pause(BOOL pause);
HRESULT GetTime(INT64 &time);
HRESULT SetVolume(INT volume);
protected:
static unsigned WINAPI InitialThreadProc(LPVOID param)
{
CBandiVideoSound_NULL *p = (CBandiVideoSound_NULL*)param;
return p->ThreadProc();
};
UINT ThreadProc();
HRESULT PlayNULL();
LONGLONG CalcTime();
LONG m_ref_count;
LONGLONG m_freq_units; // 초당 카운터 단위(1000 이면 ms단위 카운터임)
LONGLONG m_init_count; // 초기 카운터
LONGLONG m_start_time; // 시작 시간
BOOL m_playing;
CRITICAL_SECTION m_crit_sec;
BOOL m_crit_sec_inited;
HANDLE m_hevent;
HANDLE m_hthread;
UINT m_thread_id;
IBandiVideoSoundCB* m_callback;
};
@@ -0,0 +1,46 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// BandiVideoLibrary 2.1
///
/// Copyright(C) 2008-2011 BandiSoft.com All rights reserved.
///
/// Visit http://www.bandisoft.com for more information.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "bandivid.h"
class CBandiVideoDevice
{
public:
virtual ~CBandiVideoDevice() {};
virtual HRESULT Open(HWND hWnd) PURE;
virtual void Close() PURE;
virtual HRESULT Resize(INT width, INT height) PURE;
virtual HRESULT StartFrame() PURE;
virtual HRESULT EndFrame() PURE;
};
class CBandiVideoTexture
{
public:
virtual ~CBandiVideoTexture() {};
virtual HRESULT Open(INT vid_width, INT vid_height) PURE;
virtual void Close() PURE;
virtual BYTE* Lock(INT &pitch) PURE;
virtual void Unlock() PURE;
virtual HRESULT Draw(INT x, INT y, INT width, INT height) PURE;
virtual void* GetObject() PURE;
virtual BVL_PIXEL_FORMAT GetFormat() PURE;
};
@@ -0,0 +1,457 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// BandiVideoLibrary 2.1
///
/// Copyright(C) 2008-2011 BandiSoft.com All rights reserved.
///
/// Visit http://www.bandisoft.com for more information.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#include "BandiVideoTexture_DX9.h"
static BOOL GetTextureFormat(LPDIRECT3D9 d3d9, D3DFORMAT &texture_fmt_d3d, BVL_PIXEL_FORMAT &texture_fmt_bvl, int &texture_pixel_size)
{
struct
{
D3DFORMAT d3d_fmt;
BVL_PIXEL_FORMAT bvl_fmt;
int pixel_size;
} fmt_list[] =
{
{ D3DFMT_X8R8G8B8, BVLPF_X8R8G8B8, 4},
{ D3DFMT_R8G8B8, BVLPF_R8G8B8, 3},
{ D3DFMT_R5G6B5, BVLPF_R5G6B5, 2},
{ D3DFMT_X1R5G5B5, BVLPF_R5G5B5, 2},
};
D3DDISPLAYMODE d3ddm;
HRESULT hr = d3d9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
if(SUCCEEDED(hr))
{
int fmt_count = sizeof(fmt_list)/sizeof(fmt_list[0]);
for(int i = 0; i < fmt_count; i++ )
{
if(SUCCEEDED(d3d9->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, 0, D3DRTYPE_TEXTURE, fmt_list[i].d3d_fmt)))
{
texture_fmt_d3d = fmt_list[i].d3d_fmt;
texture_fmt_bvl = fmt_list[i].bvl_fmt;
texture_pixel_size = fmt_list[i].pixel_size;
return TRUE;
}
}
}
texture_fmt_d3d = D3DFMT_UNKNOWN;
texture_fmt_bvl = BVLPF_NULL;
texture_pixel_size = NULL;
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// CBandiVideoDevice_DX9 class
///
////////////////////////////////////////////////////////////////////////////////////////////////////
CBandiVideoDevice_DX9::CBandiVideoDevice_DX9()
{
// BV_DEVICE_DX9 structure
m_d3d9 = NULL;
m_d3d9_device = NULL;
m_hwnd_parent = NULL;
}
CBandiVideoDevice_DX9::~CBandiVideoDevice_DX9()
{
Close();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Open Direct3D9 Device.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoDevice_DX9::Open(HWND hWnd)
{
HRESULT hr;
LPDIRECT3D9 d3d9 = NULL;
LPDIRECT3DDEVICE9 d3d9_device = NULL;
D3DDISPLAYMODE d3ddm;
D3DPRESENT_PARAMETERS d3dpp = {0};;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
if(d3d9 == NULL)
{
ASSERT(0);
return E_FAIL;
}
hr = d3d9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
if(FAILED(hr))
{
ASSERT(0);
return hr;
}
d3dpp.hDeviceWindow = hWnd;
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &d3d9_device)))
{
ASSERT(0);
if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3d9_device)))
{
ASSERT(0);
if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3d9_device)))
{
ASSERT(0);
d3d9->Release();
return E_FAIL;
}
}
}
m_d3d9 = d3d9;
m_d3d9_device = d3d9_device;
m_hwnd_parent = hWnd;
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Close Direct3D9 Device.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
void CBandiVideoDevice_DX9::Close()
{
if(m_d3d9_device)
{
m_d3d9_device->Release();
m_d3d9_device = NULL;
}
if(m_d3d9)
{
m_d3d9->Release( );
m_d3d9 = NULL;
}
m_hwnd_parent = NULL;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Resize the Direct3D9 viewport.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoDevice_DX9::Resize(INT width, INT height)
{
if(m_d3d9_device == NULL)
return E_FAIL;
width = max(1, width);
height = max(1, height);
// Create the viewport
D3DVIEWPORT9 vp = { 0, 0, width, height, 0.0f, 1.0f };
m_d3d9_device->SetViewport( &vp );
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Begin a Direct3D9 frame.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoDevice_DX9::StartFrame()
{
if(m_d3d9_device == NULL)
return E_FAIL;
m_d3d9_device->Clear( 0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0 );
m_d3d9_device->BeginScene();
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// End a Direct3D9 frame.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoDevice_DX9::EndFrame()
{
if(m_d3d9_device == NULL)
return E_FAIL;
m_d3d9_device->EndScene();
m_d3d9_device->Present(NULL, NULL, NULL, NULL);
return S_OK;
}
/// D3DVERTEX structure
typedef struct _D3DVERTEX { // D3D Vertex
D3DVECTOR pos;
float rhw;
float tu, tv;
} D3DVERTEX;
#define D3DFVF_VERTEX (D3DFVF_XYZRHW | D3DFVF_TEX1)
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// CBandiVideoTexture_DX9 class
///
////////////////////////////////////////////////////////////////////////////////////////////////////
CBandiVideoTexture_DX9::CBandiVideoTexture_DX9(BV_DEVICE_DX9* device)
{
memcpy(&m_device, device, sizeof(BV_DEVICE_DX9));
m_texture = NULL;
m_vertex_buffer = NULL;
m_vid_width = m_vid_height = 0;
m_tex_width = m_tex_height = 0;
if(!GetTextureFormat(device->m_d3d9, m_fmt_d3d, m_fmt_bvl, m_pixel_size))
ASSERT(0);
}
CBandiVideoTexture_DX9::~CBandiVideoTexture_DX9()
{
Close();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Open a Direct3D9 texture
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoTexture_DX9::Open(INT vid_width, INT vid_height)
{
HRESULT hr;
LPDIRECT3DTEXTURE9 texture = NULL;
LPDIRECT3DDEVICE9 d3d9_device = m_device.m_d3d9_device;
BOOL pow2 = TRUE;
D3DCAPS9 Caps;
d3d9_device->GetDeviceCaps(&Caps);
if(!!(Caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL))
{
pow2 = FALSE;
}
int tex_width = CalcTexSize(vid_width, pow2);
int tex_height = CalcTexSize(vid_height, pow2);
// try to create a dynamic texture first
hr = d3d9_device->CreateTexture(tex_width, tex_height, 1,D3DUSAGE_DYNAMIC,
m_fmt_d3d, D3DPOOL_DEFAULT, &texture, 0);
if(FAILED(hr))
{
hr = d3d9_device->CreateTexture(tex_width, tex_height, 1, 0,
m_fmt_d3d, D3DPOOL_MANAGED, &texture, 0);
if(FAILED(hr))
{
Beep(1000, 1000);
ASSERT(0);
return hr;
}
}
D3DLOCKED_RECT locked_rect;
// Clear the texture to black.
if(SUCCEEDED(texture->LockRect(0, &locked_rect, NULL, NULL)))
{
// Clear the pixels.
BYTE* dest = (BYTE*) locked_rect.pBits;
int bytes = tex_width*m_pixel_size;
for(int y = 0 ; y < tex_height ; y++)
{
memset(dest, 0, bytes);
dest += locked_rect.Pitch;
}
// Unlock the DirectX texture.
texture->UnlockRect(NULL);
}
m_texture = texture;
m_vid_width = vid_width;
m_vid_height = vid_height;
m_tex_width = tex_width;
m_tex_height = tex_height;
return S_OK;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Close a Direct3D9 texture
///
////////////////////////////////////////////////////////////////////////////////////////////////////
void CBandiVideoTexture_DX9::Close()
{
m_vid_width = m_vid_height = 0;
m_tex_width = m_tex_height = 0;
if(m_texture)
{
m_texture->Release();
m_texture = NULL;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Lock a Direct3D9 teture and return the buffer address and pitch
///
////////////////////////////////////////////////////////////////////////////////////////////////////
BYTE* CBandiVideoTexture_DX9::Lock(INT &pitch)
{
D3DLOCKED_RECT rc;
BYTE *buf;
m_texture->LockRect(0, &rc, NULL, 0);
buf = (BYTE*)rc.pBits;
pitch = rc.Pitch;
return buf;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Unlock a Direct3D9 texture.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
void CBandiVideoTexture_DX9::Unlock()
{
m_texture->UnlockRect(NULL);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Draw a Direct3D9 texture.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoTexture_DX9::Draw(INT x, INT y, INT width, INT height)
{
HRESULT hr;
hr = m_device.m_d3d9_device->SetTexture(0, m_texture);
if(FAILED(hr)) return hr;
static DWORD dwAddressU, dwAddressV;
m_device.m_d3d9_device->GetSamplerState(0, D3DSAMP_ADDRESSU, &dwAddressU);
m_device.m_d3d9_device->GetSamplerState(0, D3DSAMP_ADDRESSV, &dwAddressV);
m_device.m_d3d9_device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
m_device.m_d3d9_device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
m_device.m_d3d9_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
m_device.m_d3d9_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
hr = SetVertices((float)x, (float)y, (float)width, (float)height);
m_device.m_d3d9_device->SetSamplerState(0, D3DSAMP_ADDRESSU, dwAddressU);
m_device.m_d3d9_device->SetSamplerState(0, D3DSAMP_ADDRESSV, dwAddressV);
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Set the vertices.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CBandiVideoTexture_DX9::SetVertices(float scr_x, float scr_y, float scr_width, float scr_height)
{
D3DVERTEX vertices[4];
// Set vertices
vertices[0].pos.x = scr_x;
vertices[0].pos.y = scr_y;
vertices[0].tu = 0.0f;
vertices[0].tv = 0.0f;
vertices[1].pos.x = scr_x + scr_width;
vertices[1].pos.y = scr_y;
vertices[1].tu = 1.0f * ((float)m_vid_width / m_tex_width);
vertices[1].tv = 0.0f;
vertices[2].pos.x = scr_x;
vertices[2].pos.y = scr_y + scr_height;
vertices[2].tu = 0.0f;
vertices[2].tv = 1.0f * ((float)m_vid_height / m_tex_height);
vertices[3].pos.x = scr_x + scr_width;
vertices[3].pos.y = scr_y + scr_height;
vertices[3].tu = 1.0f * ((float)m_vid_width / m_tex_width);
vertices[3].tv = 1.0f * ((float)m_vid_height / m_tex_height);
vertices[0].pos.z = vertices[1].pos.z = vertices[2].pos.z = vertices[3].pos.z = 0.0f;
vertices[0].rhw = vertices[1].rhw = vertices[2].rhw = vertices[3].rhw = 1.0f;
// Draw the vertices.
m_device.m_d3d9_device->SetVertexShader(0);
m_device.m_d3d9_device->SetFVF(D3DFVF_VERTEX);
return m_device.m_d3d9_device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(vertices[0]));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// Calculate texture size.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
int CBandiVideoTexture_DX9::CalcTexSize(int vid_size, BOOL pow2)
{
// Power-of-2 texture dimensions are required.
D3DCAPS9 caps;
m_device.m_d3d9_device->GetDeviceCaps(&caps);
if(pow2 && caps.TextureCaps & D3DPTEXTURECAPS_POW2)
{
int tex_size = 16;
while (tex_size < vid_size)
tex_size = tex_size<<1;
return tex_size;
}
return vid_size;
}
@@ -0,0 +1,78 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
///
/// BandiVideoLibrary 2.1
///
/// Copyright(C) 2008-2011 BandiSoft.com All rights reserved.
///
/// Visit http://www.bandisoft.com for more information.
///
////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include <d3d9.h>
#include "BandiVideoTexture.h"
struct BV_DEVICE_DX9
{
LPDIRECT3D9 m_d3d9;
LPDIRECT3DDEVICE9 m_d3d9_device;
HWND m_hwnd_parent;
};
class CBandiVideoDevice_DX9 : public CBandiVideoDevice, public BV_DEVICE_DX9
{
public:
CBandiVideoDevice_DX9();
virtual ~CBandiVideoDevice_DX9();
virtual HRESULT Open(HWND hWnd);
virtual void Close();
virtual HRESULT Resize(INT width, INT height);
virtual HRESULT StartFrame();
virtual HRESULT EndFrame();
};
class CBandiVideoTexture_DX9 : public CBandiVideoTexture
{
public:
CBandiVideoTexture_DX9(BV_DEVICE_DX9* device);
virtual ~CBandiVideoTexture_DX9();
virtual HRESULT Open(INT vid_width, INT vid_height);
virtual void Close();
virtual BYTE* Lock(INT &pitch);
virtual void Unlock();
virtual HRESULT Draw(INT x, INT y, INT width, INT height);
virtual void* GetObject() { return m_texture; };
virtual BVL_PIXEL_FORMAT GetFormat() { return m_fmt_bvl; };
protected:
HRESULT SetVertices(float scr_x, float scr_y, float scr_width, float scr_height);
int CalcTexSize(int vid_size, BOOL pow2);
BV_DEVICE_DX9 m_device;
LPDIRECT3DTEXTURE9 m_texture;
LPDIRECT3DVERTEXBUFFER9 m_vertex_buffer;
D3DFORMAT m_fmt_d3d;
BVL_PIXEL_FORMAT m_fmt_bvl;
int m_vid_width;
int m_vid_height;
int m_tex_width;
int m_tex_height;
int m_pixel_size;
};