Skip to content

Commit

Permalink
JNI using librtp. WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
moxie0 committed Sep 5, 2014
1 parent 380b974 commit 743a392
Show file tree
Hide file tree
Showing 15 changed files with 355 additions and 143 deletions.
5 changes: 4 additions & 1 deletion jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ include $(JNI_DIR)/webrtc/modules/audio_coding/codecs/g711/Android.mk
include $(JNI_DIR)/webrtc/modules/audio_coding/codecs/cng/Android.mk
include $(JNI_DIR)/webrtc/common_audio/vad/Android.mk

include $(JNI_DIR)/openssl/Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
Expand Down Expand Up @@ -48,7 +50,8 @@ libwebrtc_neteq \
libwebrtc_g711 \
libwebrtc_cng \
libwebrtc_spl \
libwebrtc_vad
libwebrtc_vad \
libcrypto_static


include $(BUILD_SHARED_LIBRARY)
Expand Down
29 changes: 18 additions & 11 deletions jni/redphone/AudioCodec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,32 @@

#define ECHO_TAIL_MILLIS 75

AudioCodec::AudioCodec() : enc(NULL), dec(NULL), aecm(NULL)
AudioCodec::AudioCodec() : enc(NULL), dec(NULL), aecm(NULL), initialized(0)
{ }

int AudioCodec::init() {
enc = speex_encoder_init( speex_lib_get_mode( SPEEX_MODEID_NB ) );
dec = speex_decoder_init( speex_lib_get_mode( SPEEX_MODEID_NB ) );

WebRtcAecm_Create(&aecm);
WebRtcAecm_Init(aecm, SPEEX_SAMPLE_RATE);

if (enc == NULL) {
if ((enc = speex_encoder_init(speex_lib_get_mode(SPEEX_MODEID_NB))) == NULL) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Encoder failed to initialize!");
return -1;
}

if (dec == NULL) {
if ((dec = speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_NB))) == NULL) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Decoder failed to initialize!");
return -1;
}

if (aecm == NULL) {
if (WebRtcAecm_Create(&aecm) != 0) {
__android_log_print(ANDROID_LOG_WARN, TAG, "AECM failed to create!");
return -1;
}

if (WebRtcAecm_Init(aecm, SPEEX_SAMPLE_RATE) != 0) {
__android_log_print(ANDROID_LOG_WARN, TAG, "AECM failed to initialize!");
return -1;
}


spx_int32_t config = 1;
speex_decoder_ctl(dec, SPEEX_SET_ENH, &config);
config = 0;
Expand All @@ -55,12 +56,18 @@ int AudioCodec::init() {
speex_bits_init(&enc_bits);
speex_bits_init(&dec_bits);

initialized = 1;

return 0;
}

AudioCodec::~AudioCodec() {
speex_bits_destroy( &enc_bits );
speex_bits_destroy( &dec_bits );
if (initialized) {
speex_bits_destroy( &enc_bits );
speex_bits_destroy( &dec_bits );
}

if (aecm != NULL) WebRtcAecm_Free(aecm);

if (enc != NULL) speex_encoder_destroy( enc );
if (dec != NULL) speex_decoder_destroy( dec );
Expand Down
1 change: 1 addition & 0 deletions jni/redphone/AudioCodec.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class AudioCodec {
SpeexEchoState *echo_state;

int enc_frame_size, dec_frame_size;
int initialized;

public:
AudioCodec();
Expand Down
161 changes: 80 additions & 81 deletions jni/redphone/AudioPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,124 +6,123 @@

#define TAG "AudioPlayer"

AudioPlayer::AudioPlayer(int sampleRate, int bufferFrames, WebRtcJitterBuffer &webRtcJitterBuffer, AudioCodec &audioCodec) :
webRtcJitterBuffer(webRtcJitterBuffer), audioCodec(audioCodec), sampleRate(sampleRate), bufferFrames(bufferFrames)
AudioPlayer::AudioPlayer(WebRtcJitterBuffer &webRtcJitterBuffer, AudioCodec &audioCodec) :
webRtcJitterBuffer(webRtcJitterBuffer), audioCodec(audioCodec),
bqPlayerObject(NULL), bqPlayerPlay(NULL), outputMixObject(NULL), bqPlayerBufferQueue(NULL)
{
}

AudioPlayer::~AudioPlayer() {
if (bqPlayerObject != NULL) {
(*bqPlayerObject)->Destroy(bqPlayerObject);
}

if (outputMixObject != NULL) {
(*outputMixObject)->Destroy(outputMixObject);
}
}

void AudioPlayer::playerCallback(SLAndroidSimpleBufferQueueItf bufferQueue, void *context) {
AudioPlayer* audioPlayer = static_cast<AudioPlayer*>(context);
audioPlayer->playerCallback(bufferQueue);
}

void AudioPlayer::playerCallback(SLAndroidSimpleBufferQueueItf bufferQueue) {
// __android_log_print(ANDROID_LOG_WARN, TAG, "Got player callback!");
/*
int decoded;
EncodedAudioData *encodedAudioData = jitterBuffer.getAudio();
if (encodedAudioData != NULL) {
decoded = audioCodec.decode(encodedAudioData->getData(),
encodedAudioData->getDataLen(),
outputBuffer);
delete encodedAudioData;
} else {
__android_log_print(ANDROID_LOG_WARN, TAG, "No audio available! Producing silence...");
memset(outputBuffer, 0, FRAME_SIZE * sizeof(short));
decoded = FRAME_SIZE * sizeof(short);
}
*/
int samples = webRtcJitterBuffer.getAudio(outputBuffer, FRAME_SIZE);
// __android_log_print(ANDROID_LOG_WARN, TAG, "Jitter gave me: %d samples", samples);
(*bufferQueue)->Enqueue(bufferQueue, outputBuffer, samples * sizeof(short));
}

int AudioPlayer::start(SLEngineItf *engineEnginePtr) {
SLEngineItf engineEngine = *engineEnginePtr;
SLEngineItf engineEngine = *engineEnginePtr;

SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};

SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 1, SL_SAMPLINGRATE_8,
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_LEFT, SL_BYTEORDER_LITTLEENDIAN};
SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 1, SL_SAMPLINGRATE_8,
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_LEFT, SL_BYTEORDER_LITTLEENDIAN};

SLDataSource audioSrc = {&loc_bufq, &format_pcm};
SLDataSource audioSrc = {&loc_bufq, &format_pcm};

const SLInterfaceID mixIds[] = {SL_IID_VOLUME};
const SLboolean mixReq[] = {SL_BOOLEAN_FALSE};
const SLInterfaceID mixIds[] = {SL_IID_VOLUME};
const SLboolean mixReq[] = {SL_BOOLEAN_FALSE};

if ((*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, mixIds, mixReq) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "CreateOutputMix failed!");
return -1;
}
if ((*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, mixIds, mixReq) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "CreateOutputMix failed!");
return -1;
}

if ((*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Realize OutputMix failed!");
return -1;
}
if ((*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Realize OutputMix failed!");
return -1;
}

SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
SLDataSink audioSnk = {&loc_outmix, NULL};
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
SLDataSink audioSnk = {&loc_outmix, NULL};

const SLInterfaceID ids[2] = {SL_IID_ANDROIDCONFIGURATION, SL_IID_BUFFERQUEUE};
const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
const SLInterfaceID ids[2] = {SL_IID_ANDROIDCONFIGURATION, SL_IID_BUFFERQUEUE};
const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};

if ((*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "CreateAudioPlayer failed!");
return -1;
}
if ((*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "CreateAudioPlayer failed!");
return -1;
}

SLAndroidConfigurationItf playerConfig;
SLAndroidConfigurationItf playerConfig;

if ((*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_ANDROIDCONFIGURATION, &playerConfig) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Get AndroidConfiguration interface failed!");
return -1;
}
if ((*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_ANDROIDCONFIGURATION, &playerConfig) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Get AndroidConfiguration interface failed!");
return -1;
}

SLint32 streamType = SL_ANDROID_STREAM_VOICE;
SLint32 streamType = SL_ANDROID_STREAM_VOICE;

if ((*playerConfig)->SetConfiguration(playerConfig, SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32)) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Setting SL_ANDROID_STREAM_VOICE failed!");
return -1;
}
if ((*playerConfig)->SetConfiguration(playerConfig, SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32)) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Setting SL_ANDROID_STREAM_VOICE failed!");
return -1;
}

if ((*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Realize PlayerObject failed!");
return -1;
}
if ((*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Realize PlayerObject failed!");
return -1;
}

if ((*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "GetInterface PlayerObject failed!");
return -1;
}
if ((*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "GetInterface PlayerObject failed!");
return -1;
}

if ((*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "BufferQueue failed!");
return -1;
}
if ((*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "BufferQueue failed!");
return -1;
}

if ((*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, &AudioPlayer::playerCallback, this) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "RegisterCallback failed!");
return -1;
}
if ((*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, &AudioPlayer::playerCallback, this) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "RegisterCallback failed!");
return -1;
}

memset(outputBuffer, 0, FRAME_SIZE * sizeof(short));
memset(outputBuffer, 0, FRAME_SIZE * sizeof(short));

if ((*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, outputBuffer, FRAME_SIZE * sizeof(short)) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Player enqueue failed!");
return -1;
}
if ((*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, outputBuffer, FRAME_SIZE * sizeof(short)) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Player enqueue failed!");
return -1;
}

if ((*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Play state failed!");
return -1;
}
if ((*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING) != SL_RESULT_SUCCESS) {
__android_log_print(ANDROID_LOG_WARN, TAG, "Play state failed!");
return -1;
}

return 0;
return 0;
}

void AudioPlayer::stop() {
(*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED);
(*bqPlayerBufferQueue)->Clear(bqPlayerBufferQueue);
if (bqPlayerPlay != NULL) {
(*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED);
}

if (bqPlayerBufferQueue != NULL) {
(*bqPlayerBufferQueue)->Clear(bqPlayerBufferQueue);
}
}
7 changes: 4 additions & 3 deletions jni/redphone/AudioPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ class AudioPlayer {
WebRtcJitterBuffer &webRtcJitterBuffer;
AudioCodec &audioCodec;

int sampleRate;
int bufferFrames;
// int sampleRate;
// int bufferFrames;

SLObjectItf bqPlayerObject;
SLPlayItf bqPlayerPlay;
Expand All @@ -32,7 +32,8 @@ class AudioPlayer {
short outputBuffer[FRAME_SIZE];

public:
AudioPlayer(int sampleRate, int bufferFrames, WebRtcJitterBuffer &jitterBuffer, AudioCodec &audioCodec);
AudioPlayer(WebRtcJitterBuffer &jitterBuffer, AudioCodec &audioCodec);
~AudioPlayer();

int start(SLEngineItf *engineEngine);
void stop();
Expand Down
Loading

0 comments on commit 743a392

Please sign in to comment.