vc++ (vs2008 sp1 기준) shared dll 옵션과 디버그 모드로 빌드된 dll/ocx/exe 등의 파일을
아무것도 설치되지않은 타겟 머신에 실행하려면,
C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\Debug_NonRedist\x86
아래에 있는 dll 들이 필요하다. 하지만 위 dll 들을 빌드된 파일과함께 같은 폴더에 넣어도
exe 파일을 실행시키면
"응용 프로그램 구성이 올바르지 않기 때문에 이 응용 프로그램을 시작하지 못했습니다"
메시지박스가 뜬다.
dependency walker 로 보면 dll 들이 모두 정상적으로 로드되는 것처럼 보이는데
이것은 vs2008 sp1 에서 사용하는 dll 버전이 맞지 않아서이다.
이럴 경우 stdafx.h 파일의 제일 위에
#define _BIND_TO_CURRENT_VCLIBS_VERSION 1
정의를 넣고 다시 빌드하면 타겟 머신에서 실행된다.
< 출처 - http://blog.kalmbach-software.de/2009/05/27/deployment-of-vc2008-apps-without-installing-anything/ >
2012년 5월 23일 수요일
2012년 5월 18일 금요일
ANSI <-> UTF-8 <-> Unicode 변환
int UnicodetoUTF8( LPWSTR pUniStr, int iLength, LPBYTE pUtf8Str )
{
WCHAR wChar;
BYTE szBytes[4] = { 0 };
int nbytes;
int i, j;
int iTotelLen = 0;
for( i = 0; i < iLength; i++ )
{
wChar = pUniStr[i];
if( 0x80 > wChar )
{
nbytes = 1;
szBytes[0] = (BYTE)wChar;
}
else if( 0x800 > wChar )
{
nbytes = 2;
szBytes[1] = ( wChar & 0x3f ) | 0x80;
szBytes[0] = ( ( wChar << 2 ) & 0xcf00 | 0xc000) >> 8;
}
else
{
nbytes = 3;
szBytes[2] = ( wChar & 0x3f ) | 0x80;
szBytes[1] = ( ( wChar << 2 ) & 0x3f00 | 0x8000) >> 8;
szBytes[0] = ( ( wChar << 4 ) & 0x3f0000 | 0xe00000) >> 16;
}
for( j = 0; j < nbytes; j++ )
{
pUtf8Str[iTotelLen] = szBytes[j];
iTotelLen++;
}
}
pUtf8Str[iTotelLen] = '\0';
return iTotelLen;
}
int Utf8ToUnicode( LPBYTE pUtf8Str, LPWSTR pUniStr )
{
int iIndex = 0;
int iCount = 0;
WCHAR wChar;
while( 0 != pUtf8Str[iIndex] )
{
if( ( 0xE0 == ( pUtf8Str[iIndex] & 0xE0 ) ) )
{
wChar = ( ( pUtf8Str[iIndex] & 0x0f ) << 12 ) |
( ( pUtf8Str[iIndex+1]&0x3F ) << 6 ) |
( pUtf8Str[iIndex+2] & 0x3F );
iIndex += 3;
}
else if( 0xC0 == ( pUtf8Str[iIndex] & 0xC0 ) )
{
wChar = ( ( pUtf8Str[iIndex] & 0x1F ) << 6 ) |
( pUtf8Str[iIndex+1] & 0x3F );
iIndex += 2;
}
else
{
wChar = pUtf8Str[iIndex] & 0x7F;
iIndex++;
}
pUniStr[iCount] = wChar;
iCount++;
}
pUniStr[iCount] = 0;
return iCount;
}
//char* UTF8ToANSI(char *pszCode)
int UTF8ToANSI(char *pszCode, char *pszAnsi)
{
BSTR bstrWide;
//char* pszAnsi;
int nLength;
nLength = MultiByteToWideChar(CP_UTF8, 0, pszCode, lstrlen(pszCode) + 1, NULL, NULL);
bstrWide = SysAllocStringLen(NULL, nLength);
MultiByteToWideChar(CP_UTF8, 0, pszCode, lstrlen(pszCode) + 1, bstrWide, nLength);
nLength = WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, NULL, 0, NULL, NULL);
//pszAnsi = new char[nLength];
WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, pszAnsi, nLength, NULL, NULL);
SysFreeString(bstrWide);
//return pszAnsi;
return nLength;
}
char * ANSIToUTF8(char * pszCode)
{
int nLength, nLength2;
BSTR bstrCode;
char *pszUTFCode = NULL;
nLength = MultiByteToWideChar(CP_ACP, 0, pszCode, lstrlen(pszCode), NULL, NULL);
bstrCode = SysAllocStringLen(NULL, nLength);
MultiByteToWideChar(CP_ACP, 0, pszCode, lstrlen(pszCode), bstrCode, nLength);
nLength2 = WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, pszUTFCode, 0, NULL, NULL);
pszUTFCode = (char*)malloc(nLength2+1);
WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, pszUTFCode, nLength2, NULL, NULL);
return pszUTFCode;
}
< 출처 - http://blog.kangsoo.com/14, http://skorea.tistory.com/43 >
2012년 4월 27일 금요일
ffmpeg 스케일러와 DirectDraw 를 이용한 YUV -> RGB 고속변환 출력 - YUV -> RGB Converting by ffmpeg and DirectDraw
YUV420->RGB32 변환출력의 경우 보통 이전에 포스팅된 YUV->RGB 변환방식을 사용하면된다. YUV420 버퍼를 YUV 평면에 그데로 복사하고 primary 평면에 blt 를 하면 yuv->rgb 변환과 스케일링을 동시에 고속으로 수행할 수 있다.
이번에 사용하는 방법은 YUV420 버퍼를 일반 RGB32 offscreen 평면에 스케일링한 후에 primary 평면에 blt 하는 방법이다.
이 방식은 기존 YUV->RGB 변환 방식과 성능이 동일하게 나오지만 비디오카드의 하드웨어 가속기를 사용하지않기 때문에 다른 프로세스가 하드웨어 가속기를 점유하고 있을경우에도 문제없이 사용할수 있다.
ffmpeg 스케일러 사용법과 DirectDraw 사용방법은 이전 포스팅 참조
< DirectDraw 평면 생성 >
...
ZeroMemory( &ddsd, sizeof( ddsd ) );
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = targetWidth;
ddsd.dwHeight = targetHeight;
이번에 사용하는 방법은 YUV420 버퍼를 일반 RGB32 offscreen 평면에 스케일링한 후에 primary 평면에 blt 하는 방법이다.
이 방식은 기존 YUV->RGB 변환 방식과 성능이 동일하게 나오지만 비디오카드의 하드웨어 가속기를 사용하지않기 때문에 다른 프로세스가 하드웨어 가속기를 점유하고 있을경우에도 문제없이 사용할수 있다.
ffmpeg 스케일러 사용법과 DirectDraw 사용방법은 이전 포스팅 참조
< DirectDraw 평면 생성 >
...
ZeroMemory( &ddsd, sizeof( ddsd ) );
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = targetWidth;
ddsd.dwHeight = targetHeight;
if ((hr=pDD->CreateSurface(&ddsd, &lpBackBuffer, NULL)) != DD_OK)
{
printf("failed to create back buffer surface (hr:0x%x)\n", hr);
return -1;
}
// 스케일러 생성
sws = sws_getContext(srcWidth, srcHeight, PIX_FMT_YUV420P, targetWidth, targetHeight, PIX_FMT_RGB32, SWS_BILINEAR, NULL, NULL, NULL);
...
< primary 평면에 출력 >
int VideoDDraw::draw(AVFrame *pPicture, RECT *rectTarget)
...
...
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
if ((hr=lpBackBuffer->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL)) == DD_OK)
{
// offscreen 평면에 복사 (스케일링과 동시에 복사)
LPBYTE lpSurf = (LPBYTE)ddsd.lpSurface;
LPBYTE ptr = lpSurf;
unsigned char *src_buf[4];
src_buf[0] = pPicture->data[0];
src_buf[1] = pPicture->data[1];
src_buf[2] = pPicture->data[2];
src_buf[3] = NULL;
int src_stride[4];
src_stride[0] = pPicture->linesize[0];
src_stride[1] = pPicture->linesize[1];
src_stride[2] = pPicture->linesize[2];
src_stride[3] = 0;
unsigned char *dst_buf[4];
dst_buf[0] = ptr;
dst_buf[1] = NULL;
dst_buf[2] = NULL;
dst_buf[3] = NULL;
int dst_stride[4];
dst_stride[0] = ddsd.lPitch;
dst_stride[1] = ddsd.lPitch;
dst_stride[2] = ddsd.lPitch;
dst_stride[3] = ddsd.lPitch;
// 스케일링(변환된 데이터가 들어감)
sws_scale(sws, src_buf, src_stride, 0, h, dst_buf, dst_stride);
lpBackBuffer->Unlock(NULL);
}
...
// primary 평면에 blt
hr = lpPrimary->Blt(rectTarget, lpBackBuffer, &rectSrc, DDBLT_ASYNC, NULL);
라벨:
directdraw,
ffmpeg
2012년 3월 15일 목요일
윈도우 file descriptor -> HANDLE 변환 - converting file descriptor to HANDLE
int fd = open(file_name,O_RDWR);
HANDLE hFile = (void *)_get_osfhandle(fd);
...
ReadFile();
WriteFile();
...
close(fd);
HANDLE hFile = (void *)_get_osfhandle(fd);
...
ReadFile();
WriteFile();
...
close(fd);
라벨:
win32
2012년 3월 2일 금요일
자기 ip 알아내기 - obtaining host ip address
struct hostent *fHost;
char fMyIpAddr[64];
{
char buffer[1024];
if (gethostname(buffer, sizeof(buffer)) == SOCKET_ERROR) {
printf("%s gethostname error !!!\r\n", __FUNCTION__);
return;
}
fHost = gethostbyname(buffer);
if (fHost == NULL) {
printf("%s gethostbyname error !!!\r\n", __FUNCTION__);
return;
}
sprintf(fMyIpAddr, "%d.%d.%d.%d",
((struct in_addr *)(fHost->h_addr))->S_un.S_un_b.s_b1,
((struct in_addr *)(fHost->h_addr))->S_un.S_un_b.s_b2,
((struct in_addr *)(fHost->h_addr))->S_un.S_un_b.s_b3,
((struct in_addr *)(fHost->h_addr))->S_un.S_un_b.s_b4
);
}
라벨:
socket
2012년 2월 16일 목요일
win32 shutdown 함수 사용법 - how to use win32 shutdown function
shutdown 함수는 tcp 소켓통신에서 송신/수신 채널만을 닫을때 쓰는 함수이다.
select 함수를 쓰는 구조에서 소켓통신을 종료할때 closesocket(close) 을 바로 호출하면
select 함수에서 오류가 발생하고 소켓 전체적으로 문제가 발생한다. 이때 shutdown 함수를
호출해서 통신하는 상대방에게 FIN 패킷을 전달하여 상대방 recv 함수에서 0를 리턴하게
하여 상대방쪽에서 closesocket(close) 시켜 정상적으로 tcp 소켓을 닫을때 주로 사용한다.
이때 MS 의 페이크가 있는데 리눅스와 윈도우의 shutdown 함수의 인수는 서로 반대의 의미
를 가진다. 즉,
linux windows
shutdown(SHUT_RD) => shutdown(SD_SEND)
shutdown(SHUT_WR) => shutdown(SD_RECEIVE)
tcp 통신중 상대방에게 FIN 메시지를 전달해서 상대방으로 하여금 closesocket(close) 함수를
호출하도록 유도하려면 shutdown(SD_SEND) 함수를 호출
select 함수를 쓰는 구조에서 소켓통신을 종료할때 closesocket(close) 을 바로 호출하면
select 함수에서 오류가 발생하고 소켓 전체적으로 문제가 발생한다. 이때 shutdown 함수를
호출해서 통신하는 상대방에게 FIN 패킷을 전달하여 상대방 recv 함수에서 0를 리턴하게
하여 상대방쪽에서 closesocket(close) 시켜 정상적으로 tcp 소켓을 닫을때 주로 사용한다.
이때 MS 의 페이크가 있는데 리눅스와 윈도우의 shutdown 함수의 인수는 서로 반대의 의미
를 가진다. 즉,
linux windows
shutdown(SHUT_RD) => shutdown(SD_SEND)
shutdown(SHUT_WR) => shutdown(SD_RECEIVE)
tcp 통신중 상대방에게 FIN 메시지를 전달해서 상대방으로 하여금 closesocket(close) 함수를
호출하도록 유도하려면 shutdown(SD_SEND) 함수를 호출
라벨:
socket
2012년 2월 10일 금요일
mingw64 를 이용한 ffmpeg/x264 x64 빌드 및 VC++ 링크 - building x64 ffmpeg/x264 with mingw64 and link in VC++
< ffmpeg && x264 x64 빌드 >
1. http://www.drangon.org/mingw/ 에서 mingw64 툴체인/소스 다운로드 및 설치
=> 툴체인: mingw-w64-bin-x86_64-20111106 *** 툴체인 mingw-w64-bin-x86_64-20120127 로 하면 mingw64 소스빌드 안됨 !!!
=> mingw64 소스: mingw-w64-v2.0.1 (소스 빌드하고 싶을때만)
2. msys 설치
3. ffmpeg 빌드
./configure --enable-memalign-hack
*** pr.exe, yasm.exe, pkg-config.exe(libglib-2.0_0.dll, intl.dll, libiconv-2.dll) 등 필요한것들 msys/bin 밑으로 복사
make
4. x264 빌드
./configure --cross-prefix=x86_64-w64-mingw32- --host=x86_64-pc-mingw32
endian test failed => configure 파일에서 endian test 하는 부분 전부 주석처리
x86_64-w64-mingw32-ar: command not found
x86_64-w64-mingw32-ranlib: command not found
=> mingw64/bin 아래에 ar.exe,ranlib.exe 복사본만들어서 파일 이름 위와같이 변경
dumpbin /headers libavcodec.lib | more => x64 빌드되었는지 확인
for /R %f in (*.obj *.lib) do @echo %f && dumpbin /headers %f | findstr /c:"machine (x86)"
5. mingw64 툴체인 디렉토리에서 libmingwex.a, libgcc.a 복사 링크
6. unresolved external symbol __mingw_raise_matherr 등 => libdummy.a 링크로 해결
7.
libavformat.a(tcp.o) : error LNK2001: unresolved external symbol gai_strerrorA
libavformat.a(udp.o) : error LNK2001: unresolved external symbol gai_strerrorA
=> config.h 에
#define HAVE_GETADDRINFO 1 -> 0 수정
8. VC++ 디버그 모드 빌드시 에러처리
libmingwex.a(lib64_libmingwex_a-wassert.o) : error LNK2005: _wassert already defined in MSVCRTD.lib(MSVCR90D.dll)
=> ar -d libmingwex.a lib64_libmingwex_a-wassert.o
소스수정으로 해결하는 방법
=> 툴채인 mingw-w64-bin-x86_64-20111106 버전으로 할것 !!!
=> mingw-w64-crt\misc\wassert.c 에서 __wassert() => ___wassert() 변경
*** .a 파일의 object member 보기
dumpbin /list libmingwex.a
*** dummy.c (libdummy.a) 소스 (6번 unresolved external symbol 에러해결)
int mingw_app_type = 0;
void __mingw_raise_matherr (int typ, const char *name, double a1, double a2,
double rslt)
{
}
typedef int HMODULE;
HMODULE __mingw_get_msvcrt_handle(void)
{
return 0;
}
라벨:
ffmpeg
피드 구독하기:
글 (Atom)