Commit 443bd0fd authored by Simon Morlat's avatar Simon Morlat

Merge branch 'master' of git://git.linphone.org/mediastreamer2

parents 848311e7 74af6805
......@@ -36,7 +36,9 @@ MEDIASTREAMER2_INCLUDES := \
$(LOCAL_PATH)/../../../externals/ffmpeg \
$(LOCAL_PATH)/../../../externals/ \
$(LOCAL_PATH)/../../../externals/build/ffmpeg \
$(LOCAL_PATH)/../../../externals/libvpx/
$(LOCAL_PATH)/../../../externals/libvpx/ \
$(LOCAL_PATH)/../../../externals/webrtc/ \
$(LOCAL_PATH)/../../../externals/webrtc/modules/audio_processing/aecm/include
LOCAL_MODULE := libmediastreamer2
......@@ -89,6 +91,11 @@ LOCAL_SRC_FILES = \
android/AudioSystem.cpp \
android/String8.cpp
ifneq ($(TARGET_ARCH_ABI), x86)
LOCAL_SRC_FILES += \
webrtc_aec.c
endif
##if BUILD_ALSA
ifeq ($(strip $(BOARD_USES_ALSA_AUDIO)),true)
LOCAL_SRC_FILES += alsa.c
......@@ -173,6 +180,19 @@ LOCAL_STATIC_LIBRARIES := \
libspeex \
libspeexdsp
ifneq ($(TARGET_ARCH_ABI), x86)
LOCAL_STATIC_LIBRARIES += \
libwebrtc_aecm \
libwebrtc_apm_utility \
libwebrtc_spl \
libwebrtc_system_wrappers
ifeq ($(TARGET_ARCH_ABI), armeabi-v7a)
LOCAL_STATIC_LIBRARIES += \
libwebrtc_aecm_neon \
libwebrtc_spl_neon
endif
endif
ifeq ($(strip $(BOARD_USES_ALSA_AUDIO)),true)
LOCAL_SHARED_LIBRARIES += libasound
......
......@@ -37,6 +37,9 @@ extern MSFilterDesc ms_g722_enc_desc;
extern MSFilterDesc ms_l16_enc_desc;
extern MSFilterDesc ms_l16_dec_desc;
extern MSFilterDesc ms_jpeg_writer_desc;
#ifdef __arm__
extern MSFilterDesc ms_webrtc_aec_desc;
#endif
MSFilterDesc * ms_voip_filter_descs[]={
......@@ -76,6 +79,9 @@ MSFilterDesc * ms_voip_filter_descs[]={
&ms_vp8_dec_desc,
&ms_jpeg_writer_desc,
#endif
#ifdef __arm__
&ms_webrtc_aec_desc,
#endif
NULL
};
......@@ -118,15 +118,15 @@
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
Optimization="2"
AdditionalIncludeDirectories="..\..\..\..\ortp\include;..\..\..\include"
PreprocessorDefinitions="WIN32;_CONSOLE;VIDEO_ENABLED"
PreprocessorDefinitions="WIN32;_CONSOLE;VIDEO_ENABLED;NDEBUG"
MinimalRebuild="true"
BasicRuntimeChecks="0"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
DebugInformationFormat="0"
CompileAs="1"
/>
<Tool
......@@ -140,10 +140,10 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="mediastreamer2.lib oRTP.lib"
AdditionalDependencies="mediastreamer2.lib ortp.lib"
LinkIncremental="2"
AdditionalLibraryDirectories="&quot;$(OutDir)&quot;;&quot;..\..\..\..\ortp\build\win32native\$(ConfigurationName)&quot;"
GenerateDebugInformation="true"
AdditionalLibraryDirectories="&quot;..\$(OutDir)&quot;;&quot;$(OutDir)&quot;;&quot;..\..\..\..\oRTP\build\win32native\$(ConfigurationName)&quot;"
GenerateDebugInformation="false"
SubSystem="1"
TargetMachine="1"
/>
......
......@@ -8,7 +8,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mediastreamer2", "mediastre
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mediastream", "mediastream\mediastream.vcproj", "{F158434B-A7BD-4683-87FD-33AF6B450612}"
ProjectSection(ProjectDependencies) = postProject
{4A07BB2B-F56E-4F1B-A719-D28B782AC128} = {4A07BB2B-F56E-4F1B-A719-D28B782AC128}
{4A07BB2B-F56E-4F1B-A729-D28B782AC128} = {4A07BB2B-F56E-4F1B-A729-D28B782AC128}
{8A4A1340-5B83-4698-8F2A-B8DCCA0C3285} = {8A4A1340-5B83-4698-8F2A-B8DCCA0C3285}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oRTP", "..\..\..\ortp\build\win32native\oRTP.vcproj", "{4A07BB2B-F56E-4F1B-A719-D28B782AC128}"
......
......@@ -43,7 +43,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include;..\..\..\oRTP\include;.;&quot;..\..\..\linphone-deps\include&quot;;&quot;..\..\..\linphone-deps\include\msvc&quot;"
PreprocessorDefinitions="__STDC_CONSTANT_MACROS;HAVE_LIBSWSCALE_SWSCALE_H;HAVE_LIBAVCODEC_AVCODEC_H;HAVE_SPEEXDSP;HAVE_DIRECTSHOW;VIDEO_ENABLED;ORTP_INET6;WIN32;_DEBUG;_WINDOWS;_USRDLL;MEDIASTREAMER2_EXPORTS;WINDOW_NATIVE;_CRT_SECURE_NO_DEPRECATE;_TRUE_TIME;MS2_INTERNAL"
PreprocessorDefinitions="__STDC_CONSTANT_MACROS;HAVE_LIBSWSCALE_SWSCALE_H;HAVE_LIBAVCODEC_AVCODEC_H;HAVE_SPEEXDSP;HAVE_DIRECTSHOW;VIDEO_ENABLED;ORTP_INET6;WIN32;_DEBUG;_WINDOWS;_USRDLL;MEDIASTREAMER2_EXPORTS;WINDOW_NATIVE;_CRT_SECURE_NO_DEPRECATE;_TRUE_TIME;MS2_INTERNAL;MS2_FILTERS"
MinimalRebuild="true"
ExceptionHandling="0"
BasicRuntimeChecks="0"
......@@ -75,6 +75,8 @@
ProgramDatabaseFile="$(OutDir)/mediastreamer2.pdb"
GenerateMapFile="false"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary="$(IntDir)/mediastreamer2.lib"
......@@ -129,8 +131,9 @@
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories="..\..\include;..\..\..\oRTP\include;.;&quot;..\..\..\linphone-deps\include&quot;;&quot;..\..\..\linphone-deps\include\msvc&quot;"
PreprocessorDefinitions="__STDC_CONSTANT_MACROS;HAVE_LIBSWSCALE_SWSCALE_H;HAVE_LIBAVCODEC_AVCODEC_H;HAVE_SPEEXDSP;HAVE_DIRECTSHOW;VIDEO_ENABLED;ORTP_INET6;WIN32;_DEBUG;_WINDOWS;_USRDLL;MEDIASTREAMER2_EXPORTS;WINDOW_NATIVE;_CRT_SECURE_NO_DEPRECATE;MS2_INTERNAL"
PreprocessorDefinitions="__STDC_CONSTANT_MACROS;HAVE_LIBSWSCALE_SWSCALE_H;HAVE_LIBAVCODEC_AVCODEC_H;HAVE_SPEEXDSP;HAVE_DIRECTSHOW;VIDEO_ENABLED;ORTP_INET6;WIN32;_DEBUG;_WINDOWS;_USRDLL;MEDIASTREAMER2_EXPORTS;WINDOW_NATIVE;_CRT_SECURE_NO_DEPRECATE;_TRUE_TIME;MS2_INTERNAL;MS2_FILTERS"
MinimalRebuild="true"
ExceptionHandling="0"
BasicRuntimeChecks="0"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
......@@ -150,13 +153,13 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="avcodec.lib libvpx.a swscale.lib avutil.lib ogg.lib libtheora.lib vfw32.lib Ws2_32.lib Winmm.lib ortp.lib libspeex.a libspeexdsp.a libgsm.a libgcc.a"
AdditionalDependencies="avcodec.lib libvpx.a swscale.lib avutil.lib libtheora.lib vfw32.lib Ws2_32.lib Winmm.lib ortp.lib libspeex.a libspeexdsp.a libgsm.a libgcc.a"
OutputFile="$(IntDir)/mediastreamer2.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="&quot;..\..\..\linphone-deps\lib&quot;;&quot;..\..\..\oRTP\build\win32native\$(OutDir)&quot;"
AdditionalLibraryDirectories="&quot;..\..\..\linphone-deps\lib&quot;;&quot;..\..\..\linphone-deps\lib\msvc&quot;;&quot;..\..\..\ortp\build\win32native\$(IntDir)&quot;"
IgnoreAllDefaultLibraries="false"
ModuleDefinitionFile=""
GenerateDebugInformation="true"
GenerateDebugInformation="false"
ProgramDatabaseFile="$(OutDir)/mediastreamer2.pdb"
SubSystem="2"
RandomizedBaseAddress="1"
......
......@@ -145,7 +145,7 @@ case $host in
i386-apple*|armv6-apple*|armv7-apple*|armv7s-apple*)
ios_found=yes
;;
x86_64-apple*)
x86_64-apple*|i686-apple*)
macosx_found=yes
;;
*mingw32ce)
......@@ -715,6 +715,27 @@ this check.
fi
AC_PATH_PROG(PCAP,pcap-config,false)
AM_CONDITIONAL(HAVE_PCAP, test $PCAP != false)
AC_ARG_ENABLE(pcap,
[AS_HELP_STRING([--enable-pcap], [Enable pcap library (default=no)])],
[case "${enableval}" in
yes) enable_pcap=yes ;;
no) enable_pcap=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-pcap) ;;
esac], [enable_pcap=no])
AM_CONDITIONAL(ENABLE_PCAP, test x$enable_pcap = xyes)
if test x$enable_pcap == xyes ; then
if test $PCAP != false ; then
PCAP_LIBS=`pcap-config --libs`
PCAP_CFLAGS=`pcap-config --cflags`
PCAP_CFLAGS="$PCAP_CFLAGS -DHAVE_PCAP"
AC_SUBST(PCAP_LIBS)
AC_SUBST(PCAP_CFLAGS)
fi
fi
AC_ARG_ENABLE(tests,
[AS_HELP_STRING([--enable-tests], [Enable compilation of tests (default=yes)])],
[case "${enableval}" in
......
......@@ -133,7 +133,8 @@ typedef enum MSFilterId{
MS_L16_DEC_ID,
MS_OSX_GL_DISPLAY_ID,
MS_GLXVIDEO_ID,
MS_GENERIC_PLC_ID
MS_GENERIC_PLC_ID,
MS_WEBRTC_AEC_ID
} MSFilterId;
......
......@@ -333,6 +333,7 @@ struct _VideoStream
OrtpZrtpContext *ortpZrtpContext;
srtp_t srtp_session;
MSBitrateController *rc;
bool_t prepare_ongoing;
};
typedef struct _VideoStream VideoStream;
......
......@@ -165,7 +165,7 @@ MS2_PUBLIC MSList *ms_list_copy(const MSList *list);
* Helper macro for backward compatibility.
* Use ms_base_init() and ms_voip_init() instead.
*/
#define ms_init() ms_base_init(), ms_voip_init()
#define ms_init() ms_base_init(), ms_voip_init(), ms_plugins_init()
/**
* Helper macro for backward compatibility.
......@@ -188,6 +188,14 @@ MS2_PUBLIC void ms_base_init(void);
*/
MS2_PUBLIC void ms_voip_init(void);
/**
* Load the plugins from the default plugin directory.
*
* This is just a wrapper around ms_load_plugins().
* This must be called after ms_base_init() and after ms_voip_init().
*/
MS2_PUBLIC void ms_plugins_init(void);
/**
* Load plugins from a specific directory.
* This method basically loads all libraries in the specified directory and attempts to call a C function called
......
......@@ -558,6 +558,7 @@ enum _MSFilterInterfaceId{
MSFilterVideoDecoderInterface,
MSFilterVideoCaptureInterface,
MSFilterDecoderInterface,
MSFilterVideoEncoderInterface,
};
typedef enum _MSFilterInterfaceId MSFilterInterfaceId;
......
......@@ -143,4 +143,11 @@ typedef enum _MSPlayerState MSPlayerState;
#define MS_DECODER_HAVE_PLC \
MS_FILTER_METHOD(MSFilterDecoderInterface,0,int)
/** Interface definitions for video encoders */
#define MS_VIDEO_ENCODER_HAS_BUILTIN_CONVERTER \
MS_FILTER_METHOD(MSFilterVideoEncoderInterface, 0, bool_t)
/* request a video-fast-update (=I frame for H263,MP4V-ES) to a video encoder*/
#define MS_VIDEO_ENCODER_REQ_VFU \
MS_FILTER_METHOD_NO_ARG(MSFilterVideoEncoderInterface, 1)
#endif
......@@ -339,6 +339,7 @@ MS2_PUBLIC bool_t ms_video_update_average_fps(MSAverageFPS* afps, uint32_t curre
#define MS_FILTER_GET_FPS MS_FILTER_BASE_METHOD(105,float)
/* request a video-fast-update (=I frame for H263,MP4V-ES) to a video encoder*/
/* DEPRECATED: Use MS_VIDEO_ENCODER_REQ_VFU instead */
#define MS_FILTER_REQ_VFU MS_FILTER_BASE_METHOD_NO_ARG(106)
#endif
......@@ -223,6 +223,7 @@ MS2_PUBLIC const char *ms_web_cam_get_string_id(MSWebCam *obj);
/*specific methods for static image:*/
MS2_PUBLIC void ms_static_image_set_default_image(const char *path);
MS2_PUBLIC const char *ms_static_image_get_default_image();
/** method for the "nowebcam" filter */
#define MS_STATIC_IMAGE_SET_IMAGE \
......
......@@ -116,7 +116,7 @@ public final class Hacks {
}
public static boolean needSoftvolume() {
return isGalaxySOrTab();
return isGalaxySOrTab() && Version.sdkStrictlyBelow(Version.API14_ICE_CREAM_SANDWICH_40);
}
public static boolean needRoutingAPI() {
......@@ -128,8 +128,8 @@ public final class Hacks {
}
public static boolean needPausingCallForSpeakers() {
// return false;
return isGalaxySOrTab() && !isSC02B();
return false;
//return isGalaxySOrTab() && !isSC02B();
}
public static boolean hasCamera() {
......
......@@ -258,7 +258,8 @@ AM_CFLAGS= $(ORTP_CFLAGS) \
$(STRICT_OPTIONS) \
$(LIBPULSE_CFLAGS) \
$(SPANDSP_CFLAGS) \
$(MSSILK_CFLAGS)
$(MSSILK_CFLAGS) \
$(PCAP_CFLAGS)
......@@ -285,7 +286,8 @@ libmediastreamer_voip_la_LIBADD= libmediastreamer_base.la \
$(GSM_LIBS) \
$(LIBV4L1_LIBS) \
$(LIBV4L2_LIBS) \
$(SPANDSP_LIBS)
$(SPANDSP_LIBS) \
$(PCAP_LIBS)
if BUILD_VP8
AM_CFLAGS+=$(VP8_CFLAGS)
......
......@@ -36,17 +36,13 @@ AudioRecord::AudioRecord(audio_source_t inputSource,
int sessionId){
mThis=new uint8_t[512];
mImpl=AudioRecordImpl::get();
/*HACK for gingerbread */
/*
if ((channelMask & AUDIO_CHANNEL_IN_MONO) == AUDIO_CHANNEL_IN_MONO){
channelMask=0x4;
}else if ((channelMask & AUDIO_CHANNEL_IN_STEREO) == AUDIO_CHANNEL_IN_STEREO){
channelMask=0x4|0x8;
if (mImpl->mCtorBeforeAPI17.isFound()) {
mImpl->mCtorBeforeAPI17.invoke(mThis,inputSource,sampleRate,format,channelMask,frameCount,flags,cbf,user,notificationFrames,sessionId);
} else {
/* The flags parameter was removed in Android 4.2 (API level 17). */
mImpl->mCtor.invoke(mThis,inputSource,sampleRate,format,channelMask,frameCount,cbf,user,notificationFrames,sessionId);
}
*/
mImpl->mCtor.invoke(mThis,inputSource,sampleRate,format,channelMask,frameCount,flags,cbf,user,notificationFrames,sessionId);
}
......@@ -94,14 +90,14 @@ audio_io_handle_t AudioRecord::getInput() const{
bool AudioRecordImpl::init(Library *lib){
AudioRecordImpl *impl=new AudioRecordImpl(lib);
if (!impl->mCtor.isFound()) goto fail;
if (!impl->mCtorBeforeAPI17.isFound() && !impl->mCtor.isFound()) goto fail;
if (!impl->mDtor.isFound()) goto fail;
if (!impl->mInitCheck.isFound()) goto fail;
if (!impl->mStop.isFound()) goto fail;
if (!impl->mStart.isFound()) goto fail;
sImpl=impl;
return true;
fail:
delete impl;
return false;
......@@ -111,7 +107,8 @@ AudioRecordImpl *AudioRecordImpl::sImpl=NULL;
AudioRecordImpl::AudioRecordImpl(Library *lib) :
// By default, try to load Android 2.3 symbols
mCtor(lib,"_ZN7android11AudioRecordC1EijijijPFviPvS1_ES1_ii"),
mCtorBeforeAPI17(lib,"_ZN7android11AudioRecordC1EijijijPFviPvS1_ES1_ii"),
mCtor(lib, "_ZN7android11AudioRecordC1E14audio_source_tj14audio_format_tjiPFviPvS3_ES3_ii"), // 4.2 symbol
mDtor(lib,"_ZN7android11AudioRecordD1Ev"),
mInitCheck(lib,"_ZNK7android11AudioRecord9initCheckEv"),
mStop(lib,"_ZN7android11AudioRecord4stopEv"),
......@@ -119,13 +116,13 @@ AudioRecordImpl::AudioRecordImpl(Library *lib) :
mGetMinFrameCount(lib,"_ZN7android11AudioRecord16getMinFrameCountEPijii")
{
// Try some Android 2.2 symbols if not found
if (!mCtor.isFound()) {
mCtor.load(lib,"_ZN7android11AudioRecordC1EijijijPFviPvS1_ES1_i");
if (!mCtorBeforeAPI17.isFound()) {
mCtorBeforeAPI17.load(lib,"_ZN7android11AudioRecordC1EijijijPFviPvS1_ES1_i");
}
// Then try some Android 4.1 symbols if still not found
if (!mCtor.isFound()) {
mCtor.load(lib,"_ZN7android11AudioRecordC1E14audio_source_tj14audio_format_tjiNS0_12record_flagsEPFviPvS4_ES4_ii");
if (!mCtorBeforeAPI17.isFound()) {
mCtorBeforeAPI17.load(lib,"_ZN7android11AudioRecordC1E14audio_source_tj14audio_format_tjiNS0_12record_flagsEPFviPvS4_ES4_ii");
}
if (!mStart.isFound()) {
mStart.load(lib,"_ZN7android11AudioRecord5startENS_11AudioSystem12sync_event_tEi");
......@@ -133,9 +130,12 @@ AudioRecordImpl::AudioRecordImpl(Library *lib) :
if (!mGetMinFrameCount.isFound()) {
mGetMinFrameCount.load(lib, "_ZN7android11AudioRecord16getMinFrameCountEPij14audio_format_ti");
}
// Then try some Android 4.2 symbols if still not found
if (!mGetMinFrameCount.isFound()) {
mGetMinFrameCount.load(lib, "_ZN7android11AudioRecord16getMinFrameCountEPij14audio_format_tj");
}
}
}//end of namespace
......@@ -348,6 +348,17 @@ public:
AudioRecord::callback_t,
void*,
int,
int> mCtorBeforeAPI17;
Function10<void,
void*,
audio_source_t,
uint32_t,
audio_format_t,
uint32_t,
int,
AudioRecord::callback_t,
void*,
int,
int> mCtor;
Function1<void,void*> mDtor;
Function1<status_t,const void *> mInitCheck;
......
......@@ -31,6 +31,22 @@ status_t AudioSystem::getOutputSamplingRate(int *rate, int streamType){
return AudioSystemImpl::get()->mGetOutputSamplingRate.invoke(rate,streamType);
}
status_t AudioSystem::getOutputFrameCount(int *frameCount, audio_stream_type_t streamType) {
return AudioSystemImpl::get()->mGetOutputFrameCount.invoke(frameCount, streamType);
}
status_t AudioSystem::getOutputFrameCount(int *frameCount, int streamType) {
return AudioSystemImpl::get()->mGetOutputFrameCount.invoke(frameCount, streamType);
}
status_t AudioSystem::getOutputLatency(uint32_t *latency, audio_stream_type_t streamType) {
return AudioSystemImpl::get()->mGetOutputLatency.invoke(latency, streamType);
}
status_t AudioSystem::getOutputLatency(uint32_t *latency, int streamType) {
return AudioSystemImpl::get()->mGetOutputLatency.invoke(latency, streamType);
}
status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs){
return AudioSystemImpl::get()->mSetParameters.invoke(ioHandle,keyValuePairs);
}
......@@ -48,19 +64,61 @@ audio_io_handle_t AudioSystem::getInput(audio_source_t inputSource,
AudioSystemImpl::AudioSystemImpl(Library *lib) :
// By default, try to load Android 2.3 symbols
mGetOutputSamplingRate(lib,"_ZN7android11AudioSystem21getOutputSamplingRateEPii"),
mGetOutputFrameCount(lib, "_ZN7android11AudioSystem19getOutputFrameCountEPii"),
mGetOutputLatency(lib, "_ZN7android11AudioSystem16getOutputLatencyEPji"),
mSetParameters(lib,"_ZN7android11AudioSystem13setParametersEiRKNS_7String8E"){
//mGetInput(lib,"_ZN7android11AudioSystem8getInputEijjjNS0_18audio_in_acousticsE"){
// Try some Android 4.1 symbols if not found
if (!mGetOutputSamplingRate.isFound()) {
mGetOutputSamplingRate.load(lib, "_ZN7android11AudioSystem21getOutputSamplingRateEPi19audio_stream_type_t");
}
if (!mGetOutputFrameCount.isFound()) {
mGetOutputFrameCount.load(lib, "_ZN7android11AudioSystem19getOutputFrameCountEPi19audio_stream_type_t");
}
if (!mGetOutputLatency.isFound()) {
mGetOutputLatency.load(lib, "_ZN7android11AudioSystem16getOutputLatencyEPj19audio_stream_type_t");
}
}
bool AudioSystemImpl::init(Library *lib){
AudioSystemImpl *impl=new AudioSystemImpl(lib);
int samplingRate;
int frameCount;
uint32_t latency;
status_t err;
bool buggyAndroid = false;
if (!impl->mGetOutputSamplingRate.isFound()) goto fail;
if (!impl->mGetOutputFrameCount.isFound()) goto fail;
if (!impl->mGetOutputLatency.isFound()) goto fail;
if (!impl->mSetParameters.isFound()) goto fail;
//if (!impl->mGetInput.isFound()) goto fail;
err = impl->mGetOutputSamplingRate.invoke(&samplingRate, AUDIO_STREAM_VOICE_CALL);
if (err == 0) err = impl->mGetOutputFrameCount.invoke(&frameCount, AUDIO_STREAM_VOICE_CALL);
if (err == 0) err = impl->mGetOutputLatency.invoke(&latency, AUDIO_STREAM_VOICE_CALL);
if (err == 0) {
ms_message("AUDIO_STREAM_VOICE_CALL characteristics: SamplingRate=%d, FrameCount=%d, Latency=%u", samplingRate, frameCount, latency);
} else {
ms_error("Unable to get AUDIO_STREAM_VOICE_CALL characteristics");
}
if ((frameCount > 8192) || (latency > 200)) buggyAndroid = true;
err = impl->mGetOutputSamplingRate.invoke(&samplingRate, AUDIO_STREAM_DEFAULT);
if (err == 0) err = impl->mGetOutputFrameCount.invoke(&frameCount, AUDIO_STREAM_DEFAULT);
if (err == 0) err = impl->mGetOutputLatency.invoke(&latency, AUDIO_STREAM_DEFAULT);
if (err == 0) {
ms_message("AUDIO_STREAM_DEFAULT characteristics: SamplingRate=%d, FrameCount=%d, Latency=%u", samplingRate, frameCount, latency);
} else {
ms_error("Unable to get AUDIO_STREAM_DEFAULT characteristics");
}
if (buggyAndroid) goto fail;
sImpl=impl;
return true;
fail:
delete impl;
return false;
......
......@@ -107,6 +107,9 @@ public:
// DEPRECATED
static status_t getOutputFrameCount(int* frameCount, int stream = AUDIO_STREAM_DEFAULT);
// DEPRECATED
static status_t getOutputLatency(uint32_t* latency, int stream = AUDIO_STREAM_DEFAULT);
static bool routedToA2dpOutput(audio_stream_type_t streamType);
static status_t getInputBufferSize(uint32_t sampleRate, audio_format_t format, int channelCount,
......@@ -246,6 +249,8 @@ public:
return sImpl;
}
Function2<status_t,int*,int> mGetOutputSamplingRate;
Function2<status_t, int *, int> mGetOutputFrameCount;
Function2<status_t, uint32_t *, int> mGetOutputLatency;
Function2<status_t,audio_io_handle_t,const String8 &> mSetParameters;
//Function6<audio_io_handle_t,audio_source_t,uint32_t,audio_format_t,uint32_t,audio_in_acoustics_t,int> mGetInput;
private:
......
......@@ -41,7 +41,7 @@ namespace fake_android{
/* HACK for Froyo and Gingerbread */
/* This is needed because the enum values have changed between Gingerbread and ICS */
if (mImpl->mBeforeICS) {
ms_message("Android version older than ICS, apply audio channel hack");
ms_message("Android version older than ICS, apply audio channel hack for AudioTrack");
if ((channelMask & AUDIO_CHANNEL_OUT_MONO) == AUDIO_CHANNEL_OUT_MONO) {
channelMask = 0x4;
} else if ((channelMask & AUDIO_CHANNEL_OUT_STEREO) == AUDIO_CHANNEL_OUT_STEREO) {
......
......@@ -27,6 +27,7 @@
#include "String8.h"
#define NATIVE_USE_HARDWARE_RATE 1
//#define TRACE_SND_WRITE_TIMINGS
using namespace::fake_android;
......@@ -39,6 +40,9 @@ static MSFilter * ms_android_snd_write_new(void);
static Library *libmedia=0;
static Library *libutils=0;
static const int flowControlIntervalMs = 2500;
static const int flowControlThresholdMs = 80;
static int std_sample_rates[]={
48000,44100,32000,22050,16000,8000,-1
};
......@@ -179,6 +183,8 @@ struct AndroidSndWriteData{
int nbufs;
int nFramesRequested;
bool mStarted;
uint64_t flowControlStart;
int minBufferFilling;
};
static MSFilter *android_snd_card_create_reader(MSSndCard *card){
......@@ -297,7 +303,7 @@ static void android_snd_read_preprocess(MSFilter *obj){
ad->mFilter=obj;
ad->read_samples=0;
ad->audio_source=AUDIO_SOURCE_VOICE_COMMUNICATION;
for(int i=0;i<3;i++){
for(int i=0;i<2;i++){
ad->rec=new AudioRecord(ad->audio_source,
ad->rate,
AUDIO_FORMAT_PCM_16_BIT,
......@@ -310,10 +316,7 @@ static void android_snd_read_preprocess(MSFilter *obj){
ms_error("Problem when setting up AudioRecord:%s source=%i,rate=%i,framecount=%i",strerror(-ss),ad->audio_source,ad->rate,ad->rec_buf_size);
delete ad->rec;
ad->rec=0;
if (i==0) {
ms_error("Retrying with AUDIO_SOURCE_VOICE_CALL");
ad->audio_source=AUDIO_SOURCE_VOICE_CALL;
}else if (i==1){
if (i == 0) {
ms_error("Retrying with AUDIO_SOURCE_MIC");
ad->audio_source=AUDIO_SOURCE_MIC;
}
......@@ -452,36 +455,38 @@ static void android_snd_write_cb(int event, void *user, void * p_info){
AndroidSndWriteData *ad=(AndroidSndWriteData*)user;
if (event==AudioTrack::EVENT_MORE_DATA){
int avail;
AudioTrack::Buffer *info=reinterpret_cast<AudioTrack::Buffer *>(p_info);
//ms_message("android_snd_write_cb: need to provide %i bytes",info->size);
if (ad->nbufs==0){
/*the audio subsystem takes time to start: purge the accumulated buffers while
it was not ready*/
ms_mutex_lock(&ad->mutex);
while((avail=ms_bufferizer_get_avail(&ad->bf))>0){
ms_bufferizer_skip_bytes(&ad->bf,avail);
int avail;
int ask;
ms_mutex_lock(&ad->mutex);
ask = info->size;
avail = ms_bufferizer_get_avail(&ad->bf);
/* Drop the samples accumulated before the first callback asking for data. */
if ((ad->nbufs == 0) && (avail > (ask * 2))) {
ms_bufferizer_skip_bytes(&ad->bf, avail - (ask * 2));
}
if (avail != 0) {
if ((ad->minBufferFilling == -1)) {
ad->minBufferFilling = avail;
} else if (avail < ad->minBufferFilling) {
ad->minBufferFilling = avail;
}
ms_mutex_unlock(&ad->mutex);
}
ms_mutex_lock(&ad->mutex);
if ((avail=ms_bufferizer_get_avail(&ad->bf))>=(int) info->size){
info->size = MIN(avail, ask);
#ifdef TRACE_SND_WRITE_TIMINGS
{
MSTimeSpec ts;
ms_get_cur_time(&ts);
ms_message("%03u.%03u: AudioTrack ask %d, given %d, available %d [%f ms]", (uint32_t) ts.tv_sec, (uint32_t) (ts.tv_nsec / 1000),
ask, info->size, avail, (avail / (2 * ad->nchannels)) / (ad->rate / 1000.0));
}
#endif
if (info->size > 0){
ms_bufferizer_read(&ad->bf,(uint8_t*)info->raw,info->size);
avail-=info->size;
if (avail>((100*ad->nchannels*2*ad->rate)/1000)){
ms_warning("Too many samples waiting in sound writer, dropping %i bytes",avail);
ms_bufferizer_skip_bytes(&ad->bf,avail);
}
ms_mutex_unlock(&ad->mutex);
//ms_message("%i bytes sent to the device",info->size);
}else{
ms_mutex_unlock(&ad->mutex);
//ms_message("Filling callback with silence %i bytes",info->size);
//memset(info->raw,0,info->size);
info->size=0;
info->frameCount = info->size / 2;
}
ms_mutex_unlock(&ad->mutex);
ad->nbufs++;
ad->nFramesRequested+=info->frameCount;
/*
......@@ -493,7 +498,17 @@ static void android_snd_write_cb(int event, void *user, void * p_info){
}
*/
}else if (event==AudioTrack::EVENT_UNDERRUN){
ms_warning("PCM playback underrun");
ms_mutex_lock(&ad->mutex);
#ifdef TRACE_SND_WRITE_TIMINGS
{
MSTimeSpec ts;
ms_get_cur_time(&ts);
ms_warning("%03u.%03u: PCM playback underrun: available %d", (uint32_t) ts.tv_sec, (uint32_t) (ts.tv_nsec / 1000), ms_bufferizer_get_avail(&ad->bf));
}
#else
ms_warning("PCM playback underrun: available %d", ms_bufferizer_get_avail(&ad->bf));
#endif
ms_mutex_unlock(&ad->mutex);
}else ms_error("Untracked event %i",event);
}
......@@ -530,6 +545,8 @@ static void android_snd_write_preprocess(MSFilter *obj){
ad->nbufs=0;
ms_message("AudioTrack latency estimated to %i ms",ad->tr->latency());
ad->mStarted=false;
ad->flowControlStart = obj->ticker->time;
ad->minBufferFilling = -1;
}
static void android_snd_write_process(MSFilter *obj){
......@@ -542,7 +559,26 @@ static void android_snd_write_process(MSFilter *obj){
if (!ad->mStarted)
ad->tr->start();
ms_mutex_lock(&ad->mutex);
#ifdef TRACE_SND_WRITE_TIMINGS
{
MSTimeSpec ts;
int prev_size = ad->bf.size;
ms_get_cur_time(&ts);
ms_bufferizer_put_from_queue(&ad->bf,obj->inputs[0]);
ms_message("%03u.%03u: enqueue buffer %d", (uint32_t) ts.tv_sec, (uint32_t) (ts.tv_nsec / 1000), ad->bf.size - prev_size);
}
#else
ms_bufferizer_put_from_queue(&ad->bf,obj->inputs[0]);
#endif
if (((uint32_t)(obj->ticker->time - ad->flowControlStart)) >= flowControlIntervalMs) {
int threshold = (flowControlThresholdMs * ad->nchannels * 2 * ad->rate) / 1000;
if (ad->minBufferFilling > threshold) {
ms_warning("Too many samples waiting in sound writer, dropping %i bytes", threshold);
ms_bufferizer_skip_bytes(&ad->bf, threshold);
}
ad->flowControlStart = obj->ticker->time;
ad->minBufferFilling = -1;
}
ms_mutex_unlock(&ad->mutex);
if (ad->tr->stopped()) {
ms_warning("AudioTrack stopped unexpectedly, needs to be restarted");
......
......@@ -725,7 +725,11 @@ AudioStream *audio_stream_new(int loc_rtp_port, int loc_rtcp_port, bool_t ipv6){
if (ec_desc!=NULL)
stream->ec=ms_filter_new_from_desc(ec_desc);
else
#if defined(ANDROID) && defined __arm__
stream->ec=ms_filter_new(MS_WEBRTC_AEC_ID);
#else
stream->ec=ms_filter_new(MS_SPEEX_EC_ID);
#endif
stream->evq=ortp_ev_queue_new();
rtp_session_register_event_queue(stream->session,stream->evq);
......
/*
filter-template.m
Copyright (C) 2011 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software