2009年4月25日 星期六

callback function 範例

#include <cstdlib>
#include <iostream>
using namespace std;

typedef int(*Binary_FT)(int,int);

int multiplyCB(int x, int y)
{
return x * y;
}

int additionCB(int x, int y)
{
return x + y;
}

void printFrameWork(int a, int b, char *str, Binary_FT callback)
{
int c;
c = callback(a, b);
printf("callback = %s\n", str);
printf("result = %d\n", c);
}

int main(int argc, char *argv[])
{
int integer1, integer2;
integer1 = 10;
integer2 = 20;

printf("Two inputs are %d and %d\n", integer1, integer2);
printFrameWork(integer1, integer2, "multiplyCB", multiplyCB);
printFrameWork(integer1, integer2, "additionCB", additionCB);

system("PAUSE");
return EXIT_SUCCESS;
}

執行結果:
Two inputs are 10 and 20
callback = multiplyCB
result = 200
callback = additionCB
result = 30

PJSUA - PJProject

To enable TLS supported.

Requirement:
OpenSSL library
DirectX SDK(maybe optional, but need to be configured)

To find pjproject-1.0.1\pjlib\include\pj\config.h
Add following code in it.
/**
* Support TLS in the library.
*/
#ifndef PJSIP_HAS_TLS_TRANSPORT
# define PJSIP_HAS_TLS_TRANSPORT 1
#endif

Visual Studio 2005 Configuration:
At pjsip_core project, check include path:
/IC:\lib\openssl\include

At pjsua project, it would require "libeay32MT.lib", "ssleay32MT.lib", check library path:
/LIBPATH:"C:\openssl-0.9.8i\lib"

how to comile openssl on windows; portable audio; oRTP; libeXosip2

The eXosip_event_type Variation:
INVITE a callee by rawSIPUA
je->type EXOSIP_CALL_PROCEEDING eXosip_event_type
je->type EXOSIP_CALL_RINGING eXosip_event_type
if CANCEL
je->type EXOSIP_CALL_REQUESTFAILURE eXosip_event_type (WHY!!)
--- sevaral seconds ---
je->type EXOSIP_CALL_RELEASED eXosip_event_type
END
if CALL_ANSWERED
je->type EXOSIP_CALL_ANSWERED eXosip_event_type
---- RTP stream ----
if sent CANCEL by rawSIPUA:
je->type EXOSIP_CALL_MESSAGE_ANSWERED eXosip_event_type
je->type EXOSIP_CALL_RELEASED eXosip_event_type
if received CANCEL from eyeBeam:
je->type EXOSIP_CALL_MESSAGE_NEW eXosip_event_type
je->type EXOSIP_CALL_CLOSED eXosip_event_type
je->type EXOSIP_CALL_RELEASED eXosip_event_type

Receive a INVITE from caller
je->type EXOSIP_CALL_INVITE eXosip_event_type
if ANSWERED
je->type EXOSIP_CALL_ACK eXosip_event_type

CANCEL from caller (When will I get the "EXOSIP_CALL_CANCELLED"?)

je->type EXOSIP_CALL_CLOSED eXosip_event_type
je->type EXOSIP_CALL_RELEASED eXosip_event_type

eyeBeam call rawSIPUA which is NOANSWER:
je->type EXOSIP_CALL_CLOSED eXosip_event_type
je->type EXOSIP_CALL_NOANSWER eXosip_event_type
je->type EXOSIP_CALL_RELEASED eXosip_event_type



void osip_usleep (int useconds); useconds => nano-seconds
Reference:
http://mad.cs.tut.fi/doc/mad_fcl_v1.7_man/linux/osip__port_8c-source.html#l00260


Download OpenSSL from openssl.org
Requirement: ActivePerl & OpenSSL

Configuration:

C:\include\a\openssl-0.9.8i> perl Configure VC-WIN32

C:\include\a\openssl-0.9.8i> ms\do_ms.bat

C:\include\a\openssl-0.9.8i> "C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat"

Compile OpenSSL on WIN32:

ntdll.mak(/MT) for dynamic link. nt.mak(/MD) for static link.
C:\include\a\openssl-0.9.8i> nmake -f ms\ntdll.mak

Install where you want: (here is a sample.)

C:\include\a\openssl-0.9.8i>md c:\lib\openssl
C:\include\a\openssl-0.9.8i>md c:\lib\openssl\bin
C:\include\a\openssl-0.9.8i>md c:\lib\openssl\lib
C:\include\a\openssl-0.9.8i>md c:\lib\openssl\include
C:\include\a\openssl-0.9.8i>md c:\lib\openssl\include\openssl
C:\include\a\openssl-0.9.8i>copy /b inc32\openssl\* c:\lib\openssl\include\openssl
C:\include\a\openssl-0.9.8i>copy /b out32dll\ssleay32.lib c:\lib\openssl\lib
C:\include\a\openssl-0.9.8i>copy /b out32dll\libeay32.lib c:\lib\openssl\lib
C:\include\a\openssl-0.9.8i>copy /b out32dll\ssleay32.dll c:\lib\openssl\bin
C:\include\a\openssl-0.9.8i>copy /b out32dll\libeay32.dll c:\lib\openssl\bin
C:\include\a\openssl-0.9.8i>copy /b out32dll\openssl.exe c:\lib\openssl\bin
C:\include\a\openssl-0.9.8i>copy README c:\lib\openssl
C:\include\a\openssl-0.9.8i>copy LICENSE c:\lib\openssl

Here is for batch execution used:
Basic working directory is C:\include\a\openssl-0.9.8i>

md c:\lib\openssl
md c:\lib\openssl\bin
md c:\lib\openssl\lib
md c:\lib\openssl\include
md c:\lib\openssl\include\openssl
copy /b inc32\openssl\* c:\lib\openssl\include\openssl
copy /b out32dll\ssleay32.lib c:\lib\openssl\lib
copy /b out32dll\libeay32.lib c:\lib\openssl\lib
copy /b out32dll\ssleay32.dll c:\lib\openssl\bin
copy /b out32dll\libeay32.dll c:\lib\openssl\bin
copy /b out32dll\openssl.exe c:\lib\openssl\bin
copy README c:\lib\openssl
copy LICENSE c:\lib\openssl

Reference:
http://tech.idv2.com/2006/03/27/how-to-install-openssl-under-win32/

Note:
I ran a command in INSTALL as "perl Configure VC-WIN32 --prefix=c:/some/openssl/dir" to configure,
I failed to compile it . Maybe "perl Configure --prefix=c:/some/openssl/dir VC-WIN32" could pass.

Problem: (key words: openssl ossl_typ.h 178 error type)
When I compiled eXosip2-3.2.0 with openssl, I got an error message "openssl-0.9.8i\include\openssl/ossl_typ.h(178) : error C2059: syntax error : 'type'".

Solved:
I solved it by replacing openssl library with openssl-0.9.8j.
Here is the changes between version openssl-0.9.8i and openssl-0.9.8j.

Released Version: openssl-0.9.8i
include/openssl/ossl_typ.h
#ifdef OPENSSL_SYS_WIN32
#undef X509_NAME
#undef X509_EXTENSIONS
#undef X509_CERT_PAIR
#undef PKCS7_ISSUER_AND_SERIAL
#endif

Released Version: openssl-0.9.8j
include/openssl/ossl_typ.h
#ifdef OPENSSL_SYS_WIN32
#undef X509_NAME
#undef X509_EXTENSIONS
#undef X509_CERT_PAIR
#undef PKCS7_ISSUER_AND_SERIAL
#undef OCSP_REQUEST
#undef OCSP_RESPONSE
#endif

If you don't want to see the below warning,
1>LINK : warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library

Here is a note.
Select the "Property Pages" of your project,
-> "Configuration Properties" -> "Linker" -> "Input"
-> "Ignore Specific Library" -> Input six characters, "LIBCMT".


PortAudio - portable cross-platform Audio API
http://www.portaudio.com/


PortAudio 是一跨平台的錄音及放音 API,以下是官方網站提供的開發步驟

  • Write a callback function that will be called by PortAudio when audio processing is needed.
  • Initialize the PA library and open a stream for audio I/O.
  • Start the stream. Your callback function will be now be called repeatedly by PA in the background.
  • In your callback you can read audio data from the inputBuffer and/or write data to the outputBuffer.
  • Stop the stream by returning 1 from your callback, or by calling a stop function.
  • Close the stream and terminate the library.

Windows 上測試 PortAudio 範例,以 WMME 為例

  • 將 PortAudio V1.9 解壓縮
  • 以 VS2005/VS2003 建立 Win32 console 專案
  • [前置處理器定義] 加入 PA_NO_DS;PA_NO_ASIO
  • [其它 Include 目錄] 加入 "..\portaudio\include";"..\portaudio\src\common"
  • 加入下列檔案
    • pa_allocation.c
    • pa_converters.c
    • pa_cpuload.c
    • pa_dither.c
    • pa_front.c
    • pa_process.c
    • pa_skeleton.c
    • pa_stream.c
    • pa_trace.c
    • pa_win_hostapis.c
    • pa_win_util.c
    • pa_win_wmme.c
    • pa_x86_plain_converters.c
    • pa_win_waveformat.c
  • 加入 ..\portaudio\test\patest_record.c 即可測試錄放音

Error:
Creating an Empty GUI Win32 Project.
Building with Visual C++ 2008 Express:
MSVCRTD.lib(crtexew.obj) : error LNK2019: unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup

修改如下:
Project -> xxxx Properties -> Configuration Properties -> Linker -> System ->Console (/SUBSYSTEM:CONSOLE)

Linux 平台開發步驟

在 Linux 則可以使用以下三種方式

  • Linux ALSA implementation
  • Linux Jack
  • Unix (Linux, FreeBSD, Solaris), OSS

ALSA (Advanced Linux Sound Architecture) 是 2.6 核心預設的音效子系統,取代 2.4 核心中使用的 OSS(Open Sound System)

所以我們以 ALSA 為預設的聲音處理方式

Linux 上編譯

輸入以下命令

  • ./configure && make
  • make install
  • gcc -lrc -lasound -lalsa -lpthread -o YOUR_BINARY main.c libportaudio.a

Reference:
http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/14e85604-6929-4707-a22e-8cdf596926a6
http://blog.roodo.com/richielin996/archives/2438843.html

Code Example:

int numDevices;
PaDeviceInfo *pdi;
...
numDevices = Pa_GetDeviceCount();

for( i=0; i
pdi = Pa_GetDeviceInfo( i );
printf("numDev=%d, "
"\n\tdefaultSampleRate=%f"
"\n\thostApi=%d (%s) devcnt=%d"
"\n\tmaxInputChannels=%d"
"\n\tmaxOutputChannels=%d"
"\n\tname=%s"
"\n\tstructVersion=%d"
"\n\tdefaultHighInputLatency=%f"
"\n\tdefaultHighOutputLatency=%f"
"\n\tdefaultLowInputLatency=%f"
"\n\tdefaultLowOutputLatency=%f"
"\n",
i,
pdi->defaultSampleRate,
pdi->hostApi, Pa_GetHostApiInfo(pdi->hostApi)->name, Pa_GetHostApiInfo(pdi->hostApi)->deviceCount,
pdi->maxInputChannels,
pdi->maxOutputChannels,
pdi->name,
pdi->structVersion,
pdi->defaultHighInputLatency,
pdi->defaultHighOutputLatency,
pdi->defaultLowInputLatency,
pdi->defaultLowOutputLatency
);
}
printf("dev=%d ISsupported?%d\n",Pa_GetDefaultInputDevice(),Pa_IsFormatSupported(&inputParameters,NULL,SAMPLE_RATE));

system("pause");

...

Display:

numDev=0,
defaultSampleRate=44100.000000
hostApi=0 (MME) devcnt=4
maxInputChannels=2
maxOutputChannels=0
name=M - Input
structVersion=2
defaultHighInputLatency=0.400000
defaultHighOutputLatency=0.400000
defaultLowInputLatency=0.200000
defaultLowOutputLatency=0.200000

...

Code Example: convert Int16 to Int8.
#include "pa_converters.h"
...
PaUtilConverter *converter;
short *recordedInt16Samples;
...
Int8Samples=(SAMPLE *) malloc(NUM_SECONDS * SAMPLE_RATE * NUM_CHANNELS * sizeof(char));

converter = PaUtil_SelectConverter(PA_SAMPLE_TYPE,paInt8,paDitherOff);
(*converter)(Int8Samples,1,recordedInt16Samples,1,NUM_SECONDS * SAMPLE_RATE * NUM_CHANNELS, NULL);
...


oRTP


Compiling On Windows with Visual C++ 2008 Express
1.
開啟 ortp-0.13.1\build\win32native\oRTP.vcproj
過程會有新舊版本轉換的詢問。
可直接編譯。
Output: oRTP.dll

2.
匯入RTPReceiver Project:
在 [Solution Explorer] Solution 'oRTP' 上[右鍵]->[Add]->[Existing Project]-> 開啟 ortp-0.13.1\src\tests\win_receiver\RTPReceiver.vcproj

  • 專案設定:
    RTPSender [Property] Pages -> 展開[Configuration Properties] ->
    • 在 [C/C++] -> [Additional Include Directories] -> 加入 ../../../include;
    • 同樣在 [Linker] -> [Additional Library Directories] -> 加入 ../../../build/win32native/Debug 或是 $(SolutionDir)Debug
      Note: 目前 $(SolutionDir)=> 專案的所在路徑 ortp-0.13.1/build/win32native
  • 在 RTPReceiver.cpp 裡的
    行59: err=rtp_session_recv_with_ts(session,buffer,160,ts,&havemore);
    改成: err=rtp_session_recv_with_ts(session,(uint8_t *)buffer,160,ts,&havemore);
    這樣VC9才可以讓你成功編譯。

3.
匯入RTPSender Project:
在 [Solution Explorer] Solution 'oRTP' 上[右鍵]->[Add]->[Existing Project]-> 開啟 ortp-0.13.1\src\tests\win_receiver\RTPSender.vcproj

  • 專案設定: 同上 RTPSender。
  • 在 RTPSender.cpp 裡的
    行224: rtp_session_send_with_ts(m_Session[k],m_pBuffer,nCounter,m_nUser_Timestamp);
    改成: rtp_session_send_with_ts(m_Session[k],(uint8_t *)m_pBuffer,nCounter,m_nUser_Timestamp);
    這樣VC9才可以讓你成功編譯。


struct mblk_t {
struct mblk_t *b_next; /* next message on queue */
struct mblk_t *b_prev; /* previous message on queue */
struct mblk_t *b_cont; /* next message block of message */
unsigned char *b_rptr; /* first unread data byte in message */ /* point to the rtp packet */
unsigned char *b_wptr; /* first unwritten data byte inbuffer*/
struct dblk_t *b_datap; /* data block */
};

(rtp_header_t *)(mblk_t->b_rptr)

struct dblk_t {
struct dblk_t *db_freep; /* internal use */
unsigned char *db_base; /* first byte of buffer */ /* used by ortp */
unsigned char *db_lim; /* last byte +1 of buffer */ /* used by ortp */
unsigned char *db_vbase; /* first byte of system buffer */
int (*db_cb)(); /* callback routine */ /* used by ortp */
unsigned long int db_size;
unsigned char db_ref; /* count of to this block */ /* used by ortp */
unsigned char db_type; /* message type */
unsigned char db_class; /* internal use */
unsigned char db_id;
};