From Skypekit official site: SkypeKit is no longer accepting new developer registrations. If you are developing websites or applications that you want to integrate with Skype, check out the Skype URIs.
too bad that URI is not good for home automation. How a stupid decision it is!
SkypeKit on DM36x-IPNC
Development Note to Port SkypeKit to DM368-IPNC
Sunday, July 6, 2014
Thursday, May 31, 2012
[SKYPEKIT][DM368][IPNC] Audio PCM/ALSA Experiment on DM368-IPNC,
The previous trial on skypekit audio ([SKYPEKIT][DM368][IPNC] Audio PCM Experiment on DM368-IPNC) was using OSS (/dev/dsp) for Audio PCM host input and output voice. The major cons are that it's lack of powerful helper functions, i.e. API, which might lead to delay.
After trying to implement Voice RTP host (a nightmare since DM368 is lack of hardware G.729 encode/decode support. Even if using G.711, the CPU usage is not significant less compared to deploying Audio PCM host), we decided to use ALSA instead of OSS.
The code to start with is still PCMHost loopback. The steps are:
1. Remove buffer manipulation codes
2. Open ALSA device for voice input and output
I decided to put the initialization in Start():PCMLoopback. If the deviceType is INPUT_DEVICE, the code would be something like:
Similarly, if deviceType == OUTPUT_DEVICE, the code would be
3. Close ALSA device when necessary
I put them in Stop()::PCMLoopback, maybe there is good idea to put it at other place like ~PCMLoopback() or Uninit().
After trying to implement Voice RTP host (a nightmare since DM368 is lack of hardware G.729 encode/decode support. Even if using G.711, the CPU usage is not significant less compared to deploying Audio PCM host), we decided to use ALSA instead of OSS.
The code to start with is still PCMHost loopback. The steps are:
1. Remove buffer manipulation codes
Similar to what we did in OSS, we don't need loopback_buf anymore, as well as it's Pull() and Push() methods. It's safe to remove those codes in Run()@PCMHostLoopback.c. It can save you some CPU time.
2. Open ALSA device for voice input and output
I decided to put the initialization in Start():PCMLoopback. If the deviceType is INPUT_DEVICE, the code would be something like:
int rc, dir = 0;
unsigned int val;
snd_pcm_hw_params_t *hw_params = NULL;
snd_pcm_uframes_t uframe;
if(capture_handle == 0)
{
rc = snd_pcm_open(&capture_handle, "default", SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0)
{
SID_ERROR("unable to open pcm device: %s\n", snd_strerror(rc));
return PCMIF_ERROR;
}
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(&hw_params);
/* Fill it in with default values. */
snd_pcm_hw_params_any(capture_handle, hw_params);
/* Sampling rate*/
val = input_sampleRate;
snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &val, 0);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(capture_handle, hw_params, SND_PCM_FORMAT_S16_LE);
/* Interleaved mode */
snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
/* Num channels */
snd_pcm_hw_params_set_channels(capture_handle, hw_params, 1);
uframe = (output_sampleRate / 100);
rc = snd_pcm_hw_params_set_period_size_near(capture_handle, hw_params, &uframe, 0);
if (rc < 0)
{
SID_ERROR("snd_pcm_hw_params_set_period_size_near %s\n", snd_strerror(rc));
return PCMIF_ERROR;
}
rc = snd_pcm_hw_params(capture_handle, hw_params);
if (rc < 0)
{
SID_ERROR("snd_pcm_hw_params %s\n", snd_strerror(rc));
return PCMIF_ERROR;
}
Similarly, if deviceType == OUTPUT_DEVICE, the code would be
int rc, dir = 0;
unsigned int val;
snd_pcm_hw_params_t *hw_params = NULL;
snd_pcm_uframes_t uframe;
if(playback_handle == 0)
{
rc = snd_pcm_open(&playback_handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (rc < 0)
{
SID_ERROR("unable to open pcm device: %s\n", snd_strerror(rc));
return PCMIF_ERROR;
}
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(&hw_params);
/* Fill it in with default values. */
snd_pcm_hw_params_any(playback_handle, hw_params);
/* Sampling rate*/
val = output_sampleRate;
snd_pcm_hw_params_set_rate_near(playback_handle, hw_params, &val, 0);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(playback_handle, hw_params, SND_PCM_FORMAT_S16_LE);
/* Interleaved mode */
snd_pcm_hw_params_set_access(playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
/* Num channels */
snd_pcm_hw_params_set_channels(playback_handle, hw_params, 1);
uframe = (output_sampleRate / 100);
rc = snd_pcm_hw_params_set_period_size_near(playback_handle, hw_params, &uframe, 0);
if (rc < 0)
{
SID_ERROR("snd_pcm_hw_params_set_period_size_near %s\n", snd_strerror(rc));
return PCMIF_ERROR;
}
rc = snd_pcm_hw_params(playback_handle, hw_params);
if (rc < 0)
{
SID_ERROR("snd_pcm_hw_params %s\n", snd_strerror(rc));
return PCMIF_ERROR;
}
3. Close ALSA device when necessary
I put them in Stop()::PCMLoopback, maybe there is good idea to put it at other place like ~PCMLoopback() or Uninit().
snd_pcm_close(playback_handle);
snd_pcm_close(capture_handle);
4. Feed data to ALSA playback and Deliver ALSA captured data to Skypekit Runtime
in Run()::PCMLoopback
if output_started is true, using
len = snd_pcm_writei(playback_handle, output_buf.m_data.data(), output_buf.m_data.size()>>1);
to send voice out.
if input_started is true, using
len = snd_pcm_readi(capture_handle, input_buf.m_data.data(), input_sampleRate / 100); //input_buf.m_data.size());
to get captured data and send it to Skypekit Runtime by invoking InputDeviceReady().
Do remember to call snd_pcm_recover() if snd_pcm_readi or snd_pcm_writei returns error.
The CPU usage of using ALSA is almost the same as we are using OSS, but we can get more control on audio I/O.
Easy job, right?
Friday, May 4, 2012
[SKYPEKIT][DM368][IPNC] Audio PCM Experiment on DM368-IPNC
The very beginning experiment of porting Skypekit to DM368-IPNC is enabling Audio PCM to test voice conversation. With basic DM368-IPNC developing experience, you shall be able to make it work within few days.
Before starting, please make sure you have scanned Audio PCM Tutorial from Skype Developer Network. (You have to join in and log in first to read the article)
Steps:
1. Prepare Skypekit environment
Skypekit runtime - linux-armv5-skypekit-voicepcm-novideo (version 4.1.2)
Skypekit client - skypekitclient (version 4.1.2), which can be build at directory skypekit-sdk_sdk-4.1.2/interfaces/skype/cpp_embedded
If you have no idea of those, please check the other article for startup [SKYPEKIT][DM368][IPNC] Starting Skypekit on DM368-IPNC - setup environment and build the 1st tutorial example
2. Build reference audio PCMHost loopback
Following Audio PCM Quick Start, you can get PCMHost loopback "voicepcmhost-loopback" and try it with the UI skypekitclient.
3. Modify voicepcmhost-loopback
By tracing voicepcmhost-loopback reference code (precisely, PCMLoopback.cpp), you can see the voice data loopback ( is actually done by Run() method of the class PCMLoopback. The thing we are going to do is quite simple - get and put the voice data from/to physical device, instead of using loopback_buf.
The audio device we can use is /dev/dsp. According to Skypekit requirement, we need 16bit PCM, and at least 8k sample rate. Thus, the code would be something like:
fd = open("/dev/dsp", O_RDWR);
status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg);
status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg);
in the if statement "if(output_started)", add something like
write(fd, output_buf.m_data.data(), output_buf.m_data.size()); // for incoming voice
in the if statement "if(input_started)", add something like
read(fd, input_buf.m_data.data(), input_buf.m_data.size()); // for outgoing voice
4. Kill av_server.out
av_server.out consumes MIC input data (see DRV_audioOpen() @ drv_audio.c) which we shall avoid. To simplify this experiment, we just kill av_server.out.
After all, we can repeat Step 2 to try our new voicepcmhost-loopback, which provides 2-way skype voice communication. Easy work, isn't it?
Tuesday, April 24, 2012
[SKYPEKIT][DM368][IPNC] H.264 QQVGA Encoding with DM36x
According to Skypekit Video RTP host requirement, "Skype requires that all video endpoints support 160x120 video (QQVGA) to ensure a minimum level
of interoperability." Thus, the first job is to ask DM368 to do QQVGA encoding (in H.264).
It seemed to be an easy job since in UI_setConfig( )@avServerUi.c, we can set
However, it's not easy as dummy thought (代誌不是像憨人想的那麼簡單). you will find that the change will result in VIDEO_encodeTskRun error because the alg framework ALG_vidEncRun( )@alg_vidEnc.c returns error with message
the 2nd returned error code (extendedError, 0x8010 in hex) means IH264VENC_ERR_PROCESS_CALL
It's quite annoyed because there is not other detail information describing this error and the user's guide "H.264 Base/Main/High Profile Encoder on DM365/DM368" doesn't either. Thankfully by searching e2e forum, I found someone had the same problem, in post
It seemed to be an easy job since in UI_setConfig( )@avServerUi.c, we can set
config->encodeConfig[i].cropWidth andto desired resolution and let the framework to do the rest.
config->encodeConfig[i].cropHeight
However, it's not easy as dummy thought (代誌不是像憨人想的那麼簡單). you will find that the change will result in VIDEO_encodeTskRun error because the alg framework ALG_vidEncRun( )@alg_vidEnc.c returns error with message
CODEC RUN FAIL ERROR CODE: -1 32784 12206
ERROR (videoEncodeThr.c|VIDEO_encodeTskRun|292): ALG_vidEncRun()
because of the print statement
OSA_printf("CODEC RUN FAIL ERROR CODE: %d %d %d\n", status, 264OutArgs.videncOutArgs.extendedError, h264OutArgs.videncOutArgs.bytesGenerated);
the 2nd returned error code (extendedError, 0x8010 in hex) means IH264VENC_ERR_PROCESS_CALL
It's quite annoyed because there is not other detail information describing this error and the user's guide "H.264 Base/Main/High Profile Encoder on DM365/DM368" doesn't either. Thankfully by searching e2e forum, I found someone had the same problem, in post
DM36x H.264 encoder error 0x8010 at relatively high bitrates+low resolutions
Although it doesn't provide the exact solution, the hint is to reduce desired bitrate, which is a parameter of av_server.out if you are using IPNC platform.
for QQVGA, you can set the bitrate as low as 320k, or even set 0. rather than 5M in original, and the error is gone and I am able to get streamed QQVGA H264 video successfully.
Tuesday, April 10, 2012
[SKYPEKIT][DM368][IPNC] Revised: the Reason of "Account::LOGOUTREASON Unknown:673000" in Tutorials
In Starting Skypekit on DM368-IPNC - setup environment and build the 1st tutorial example, we discussed "Account::LOGOUTREASON<Unknown:673000>" problem in end of the article. There we introduced a workaround to reduce the chance generating this error message.
After digging into skypekit examples a little bit deeper, the root cause *might be* found because improperly trying to get "GetPropLogoutreason", in MyAccount::OnChange@tutorial_common.h.
The original implementation imply that after Account::P_STATUS fired, the Account::LOGOUTREASON has already prepared, which *might* not be true. It can only be sure after Account::P_LOGOUTREASON is fired.
To fix this, try to catch Account::P_LOGOUTREASON at MyAccount::OnChange, Then you are safe to invoke
this->GetPropLogoutreason for the logout reason.
Note:
Sorry I cannot put the code piece here because of skypekit legal term. but it's easy to patch by yourselves even with even little of experience of skypekit.
After digging into skypekit examples a little bit deeper, the root cause *might be* found because improperly trying to get "GetPropLogoutreason", in MyAccount::OnChange@tutorial_common.h.
The original implementation imply that after Account::P_STATUS fired, the Account::LOGOUTREASON has already prepared, which *might* not be true. It can only be sure after Account::P_LOGOUTREASON is fired.
To fix this, try to catch Account::P_LOGOUTREASON at MyAccount::OnChange, Then you are safe to invoke
this->GetPropLogoutreason for the logout reason.
Note:
Sorry I cannot put the code piece here because of skypekit legal term. but it's easy to patch by yourselves even with even little of experience of skypekit.
Monday, March 26, 2012
[SKYPEKIT][DM368][IPNC] Starting Skypekit on DM368-IPNC - setup environment and build the 1st tutorial example
It's interesting to have this project to enable Skype on DM368 device, specifically, Appro's IPNC. I got support from boss to initiate this trial project, after requesting funding for more than 6 months.
First of all, I registered "SkypeKit for Embedded", a $5 cost. According to the instruction, I did
1. register a (test) application and version at https://developer.skype.com/
2. download a runtime and an application token (key pair).
(and sdk. I got skypekit-sdk_sdk-3.7.0.20_xxxxxxx.tar.gz for sdk, linux-armv5-skypekit-voicepcm-videortp_3.7.0.103_xxxxxxx.tar.gz for runtime, and a keypair.pem)
3. save the key pair as keypair.pem file in examples/cpp/tutorial/keypair
4. re-build C++ wrapper from project files located in interfaces/skype/cpp_embedded/build directory.
5. build tutorials from project files located in examples/cpp/tutorial/build
As a dm368-ipnc user, life is not that easy since you won't get it compiled or worked just follow the instructions above.
Note: this article includes sdk 3.7 and 4.1.2. Although 3.7 is stable, officially, I found that 4.1.2(beta) is actually more stable than 3.7.
[This Section is for SDK 3.7]
To make tutorial_1 running, the steps are:
1. Prepare the build environment.
here I used Rules.make to setup parameters so the only thing to be patched is including "Rules.make" in Makefile.
Rules.make example:
2. Build skypekit-cyassl_lib and skypekit-cppwrapper_2_lib.
this is required before build tutorial example!
run make at [skypekit-sdk-dir]/interfaces/skype/cpp_embedded/build/gmake/
3. Build target tutorial
before building, I had to copy keypair.pem to [skypekit-sdk-dir]/examples/cpp/tutorial/keypair/
enter [skypekit-sdk-dir]/examples/cpp/tutorial/build/gmake/
make tutorial_1
now I have executable tutorial_1 and skypekit runtime linux-armv5-skypekit-voicepcm-videortp in hand. Per instruction, execute runtime as daemon and run tutorial_1 should demonstrate skype login and logout process.
./linux-armv5-skypekit-voicepcm-videortp &
it will show some information like below
./tutorial_1 [skypename] [password]
Unfortunately, this test failed with messages below
4. Build (loopback) video and voice host engines
since my runtime is of videortp and voicepcm option, run make at
5. Test tutorial 1 again
./linux-armv5-skypekit-voicepcm-videortp &
./videortphost-loopback &
./voicepcmhost-loopback &
./tutorial_1 [skypename] [password]
and the terminal shows
Note:
if there is segmentation fault or Account::LOGOUTREASON.SERVER_CONNECT_FAILED, try to run ./killall and stop av_server.out. your system memory maybe limited to run this tutorial
[This Section is for SDK 4.1.2(Beta 4.1)]
The C++ wrapper library no longer ships with pre-made project files. Instead, the SDK now comes with CMake scripts. Thus, I had to change [skypekit_sdk]/interfaces/skype/cpp_embedded/cmake-build/CMakeCache.txt which was generated by running [skype_sdk]/interfaces/skype/cpp_embedded/BuildWithCmake.sh.
the change example including:
Note2: Sometime there is login error with message "Account::LOGOUTREASON.SERVER_CONNECT_FAILED" or "Account::LOGOUTREASON<Unknown:673000>" or
"Account::LOGOUTREASON<Unknown:0>"
The reason is not clarified as far (MAR2012) but it should be skypekit runtime problem. I added a delay before invoking "LoginWithPassword" (i.e. Delay(50)), and tried certain times if failed, to remedy this problem. The insertion of Delay can reduce the chance to be forced logout anyway.
First of all, I registered "SkypeKit for Embedded", a $5 cost. According to the instruction, I did
1. register a (test) application and version at https://developer.skype.com/
2. download a runtime and an application token (key pair).
(and sdk. I got skypekit-sdk_sdk-3.7.0.20_xxxxxxx.tar.gz for sdk, linux-armv5-skypekit-voicepcm-videortp_3.7.0.103_xxxxxxx.tar.gz for runtime, and a keypair.pem)
3. save the key pair as keypair.pem file in examples/cpp/tutorial/keypair
4. re-build C++ wrapper from project files located in interfaces/skype/cpp_embedded/build directory.
5. build tutorials from project files located in examples/cpp/tutorial/build
As a dm368-ipnc user, life is not that easy since you won't get it compiled or worked just follow the instructions above.
Note: this article includes sdk 3.7 and 4.1.2. Although 3.7 is stable, officially, I found that 4.1.2(beta) is actually more stable than 3.7.
[This Section is for SDK 3.7]
To make tutorial_1 running, the steps are:
1. Prepare the build environment.
here I used Rules.make to setup parameters so the only thing to be patched is including "Rules.make" in Makefile.
Rules.make example:
TARGET_ARCH := armv5le-eabiyou could also want to install utility "premake" from industriousone
MVTOOL_PREFIX := arm_v5t_le-
TOOLCHAIN_PREFIX := /opt/mv_pro_5.0.0/montavista/pro/devkit/arm/v5t_le/bin/$(MVTOOL_PREFIX)
CC := $(MVTOOL_PREFIX)gcc
CXX := $(MVTOOL_PREFIX)g++
AR := $(MVTOOL_PREFIX)ar
LD := $(MVTOOL_PREFIX)ld
export CC
export CXX
export AR
2. Build skypekit-cyassl_lib and skypekit-cppwrapper_2_lib.
this is required before build tutorial example!
run make at [skypekit-sdk-dir]/interfaces/skype/cpp_embedded/build/gmake/
3. Build target tutorial
before building, I had to copy keypair.pem to [skypekit-sdk-dir]/examples/cpp/tutorial/keypair/
enter [skypekit-sdk-dir]/examples/cpp/tutorial/build/gmake/
make tutorial_1
now I have executable tutorial_1 and skypekit runtime linux-armv5-skypekit-voicepcm-videortp in hand. Per instruction, execute runtime as daemon and run tutorial_1 should demonstrate skype login and logout process.
./linux-armv5-skypekit-voicepcm-videortp &
it will show some information like below
SkypeRuntime Copyright (C) 2003-2012 Skype Technologies S.A.
SkypeRuntime Version: 3.7/linux-armv5-skypekit-voicepcm-videortp_3.7.0.103_xxxxxxx
Proprietary and confidential, do not share this application.
./tutorial_1 [skypename] [password]
Unfortunately, this test failed with messages below
*****************************************************************there are several discussions at skypekit forum but no explicitly answer as far. Mostly "Account::LOGOUTREASON<Unknown:0>" problem instead. After digging a little bit deeper, I found that the answer is simple - we need not only C++ wrapper from project files located in interfaces/skype/cpp_embedded/build directory, but also video/voice host to hook with SkypeKit API. Of course, it is not necessary if your skypekit runtime is chat only (i.e. no video and voice post fix)
SkypeKit Tutorial, Step 1 - Login with skypename and password.
*****************************************************************
Creating skype ..
Getting account ..
Logging in..
UnixSocket.cpp:101(Connect): /tmp/vidrtp_from_skypekit_key: failed to connect: error #111
UnixSocket.cpp:101(Connect): /tmp/pcm_from_skypekit_key: failed to connect: error #111
PCM client connection was not established.
SidPCMClient.cpp:43(SkypePCMInterfaceGet): Skypekit will exit.
4. Build (loopback) video and voice host engines
since my runtime is of videortp and voicepcm option, run make at
[skypekit-sdk-dir]/reference/videortphost-loopbackthe executables can be found under ./build respectively.
[skypekit-sdk-dir]/reference/voicepcmhost-loopback
5. Test tutorial 1 again
./linux-armv5-skypekit-voicepcm-videortp &
./videortphost-loopback &
./voicepcmhost-loopback &
./tutorial_1 [skypename] [password]
and the terminal shows
*****************************************************************
SkypeKit Tutorial, Step 1 - Login with skypename and password.
*****************************************************************
Creating skype ..
Getting account ..
Logging in..
AVTransportWrapper (/tmp/pcm_from_skypekit_key): connected!
AVTransportWrapper (/tmp/pcm_from_skypekit_key): connected!
AVTransportWrapper (/tmp/pcm_to_skypekit_key): connected!
AVTransportWrapper (/tmp/pcm_to_skypekit_key): connected!
Init
UseDefaultDevice: INPUT_DEVICE
UseDefaultDevice: OUTPUT_DEVICE
UseDefaultDevice: NOTIFICATION_DEVICE
GetCurrentDevice: INPUT_DEVICE, guid0
UseDevice: INPUT_DEVICE, guid0
UseDevice: OUTPUT_DEVICE, guid0
UseDefaultDevice: NOTIFICATION_DEVICE
GetCurrentDevice: INPUT_DEVICE, guid0
GetDevices: INPUT_DEVICE
GetDevices: OUTPUT_DEVICE
Stop: INPUT_DEVICE
Stop: OUTPUT_DEVICE
Stop: NOTIFICATION_DEVICE
UseDevice: INPUT_DEVICE, guid0
UseDevice: OUTPUT_DEVICE, guid0
UseDefaultDevice: NOTIFICATION_DEVICE
GetCurrentDevice: INPUT_DEVICE, guid0
UseDevice: INPUT_DEVICE, guid0
UseDevice: OUTPUT_DEVICE, guid0
UseDefaultDevice: NOTIFICATION_DEVICE
GetCurrentDevice: INPUT_DEVICE, guid0
GetCurrentDevice: INPUT_DEVICE, guid0
Start: INPUT_DEVICE
Stop: INPUT_DEVICE
GetCurrentDevice: OUTPUT_DEVICE, guid0
GetCurrentDevice: NOTIFICATION_DEVICE, guid0
Start: OUTPUT_DEVICE
Stop: OUTPUT_DEVICE
Stop: INPUT_DEVICE
Stop: OUTPUT_DEVICE
Stop: NOTIFICATION_DEVICE
Login complete.
Press ENTER to log out...
Note:
if there is segmentation fault or Account::LOGOUTREASON.SERVER_CONNECT_FAILED, try to run ./killall and stop av_server.out. your system memory maybe limited to run this tutorial
[This Section is for SDK 4.1.2(Beta 4.1)]
The C++ wrapper library no longer ships with pre-made project files. Instead, the SDK now comes with CMake scripts. Thus, I had to change [skypekit_sdk]/interfaces/skype/cpp_embedded/cmake-build/CMakeCache.txt which was generated by running [skype_sdk]/interfaces/skype/cpp_embedded/BuildWithCmake.sh.
the change example including:
CMAKE_AR:FILEPATHthe others are similar to SDK 3.7
CMAKE_CXX_COMPILER:FILEPATH
CMAKE_C_COMPILER:FILEPATH
CMAKE_LINKER:FILEPATH
CMAKE_MAKE_PROGRAM:FILEPATH
CMAKE_OBJCOPY:FILEPATH
CMAKE_OBJDUMP:FILEPATH
CMAKE_STRIP:FILEPATH
Note2: Sometime there is login error with message "Account::LOGOUTREASON.SERVER_CONNECT_FAILED" or "Account::LOGOUTREASON<Unknown:673000>" or
"Account::LOGOUTREASON<Unknown:0>"
The reason is not clarified as far (MAR2012) but it should be skypekit runtime problem. I added a delay before invoking "LoginWithPassword" (i.e. Delay(50)), and tried certain times if failed, to remedy this problem. The insertion of Delay can reduce the chance to be forced logout anyway.
Subscribe to:
Posts (Atom)