blob: 726e98b5bb321b00e6b07c657694e5b6b9cf938e [file] [log] [blame]
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdint.h>
19#include <string.h>
20#include <errno.h>
21#include <fcntl.h>
22#include <sys/epoll.h>
23#include <sys/types.h>
24#include <sys/socket.h>
25#include <sys/stat.h>
26#include <sys/time.h>
27#include <time.h>
28#include <arpa/inet.h>
29#include <netinet/in.h>
30
31#define LOG_TAG "AudioGroup"
32#include <cutils/atomic.h>
33#include <utils/Log.h>
34#include <utils/Errors.h>
35#include <utils/RefBase.h>
36#include <utils/threads.h>
37#include <utils/SystemClock.h>
38#include <media/AudioSystem.h>
39#include <media/AudioRecord.h>
40#include <media/AudioTrack.h>
41#include <media/mediarecorder.h>
42
43#include "jni.h"
44#include "JNIHelp.h"
45
46#include "AudioCodec.h"
47
48extern int parse(JNIEnv *env, jstring jAddress, int port, sockaddr_storage *ss);
49
50namespace {
51
52using namespace android;
53
54int gRandom = -1;
55
56// We use a circular array to implement jitter buffer. The simplest way is doing
57// a modulo operation on the index while accessing the array. However modulo can
58// be expensive on some platforms, such as ARM. Thus we round up the size of the
59// array to the nearest power of 2 and then use bitwise-and instead of modulo.
60// Currently we make it 256ms long and assume packet interval is 32ms or less.
61// The first 64ms is the place where samples get mixed. The rest 192ms is the
62// real jitter buffer. For a stream at 8000Hz it takes 4096 bytes. These numbers
63// are chosen by experiments and each of them can be adjusted as needed.
64
65// Other notes:
66// + We use elapsedRealtime() to get the time. Since we use 32bit variables
67// instead of 64bit ones, comparison must be done by subtraction.
68// + Sampling rate must be multiple of 1000Hz, and packet length must be in
69// milliseconds. No floating points.
70// + If we cannot get enough CPU, we drop samples and simulate packet loss.
71// + Resampling is not done yet, so streams in one group must use the same rate.
72// For the first release we might only support 8kHz and 16kHz.
73
74class AudioStream
75{
76public:
77 AudioStream();
78 ~AudioStream();
79 bool set(int mode, int socket, sockaddr_storage *remote,
Chia-chi Yeh4033a672010-09-16 18:36:45 +080080 AudioCodec *codec, int sampleRate, int sampleCount,
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +080081 int codecType, int dtmfType);
82
83 void sendDtmf(int event);
84 bool mix(int32_t *output, int head, int tail, int sampleRate);
85 void encode(int tick, AudioStream *chain);
86 void decode(int tick);
87
88private:
89 enum {
90 NORMAL = 0,
91 SEND_ONLY = 1,
92 RECEIVE_ONLY = 2,
93 LAST_MODE = 2,
94 };
95
96 int mMode;
97 int mSocket;
98 sockaddr_storage mRemote;
99 AudioCodec *mCodec;
100 uint32_t mCodecMagic;
101 uint32_t mDtmfMagic;
102
103 int mTick;
104 int mSampleRate;
105 int mSampleCount;
106 int mInterval;
107
108 int16_t *mBuffer;
109 int mBufferMask;
110 int mBufferHead;
111 int mBufferTail;
112 int mLatencyScore;
113
114 uint16_t mSequence;
115 uint32_t mTimestamp;
116 uint32_t mSsrc;
117
118 int mDtmfEvent;
119 int mDtmfStart;
120
121 AudioStream *mNext;
122
123 friend class AudioGroup;
124};
125
126AudioStream::AudioStream()
127{
128 mSocket = -1;
129 mCodec = NULL;
130 mBuffer = NULL;
131 mNext = NULL;
132}
133
134AudioStream::~AudioStream()
135{
136 close(mSocket);
137 delete mCodec;
138 delete [] mBuffer;
139 LOGD("stream[%d] is dead", mSocket);
140}
141
142bool AudioStream::set(int mode, int socket, sockaddr_storage *remote,
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800143 AudioCodec *codec, int sampleRate, int sampleCount,
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800144 int codecType, int dtmfType)
145{
146 if (mode < 0 || mode > LAST_MODE) {
147 return false;
148 }
149 mMode = mode;
150
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800151 mCodecMagic = (0x8000 | codecType) << 16;
152 mDtmfMagic = (dtmfType == -1) ? 0 : (0x8000 | dtmfType) << 16;
153
154 mTick = elapsedRealtime();
155 mSampleRate = sampleRate / 1000;
156 mSampleCount = sampleCount;
157 mInterval = mSampleCount / mSampleRate;
158
159 // Allocate jitter buffer.
160 for (mBufferMask = 8192; mBufferMask < sampleRate; mBufferMask <<= 1);
161 mBufferMask >>= 2;
162 mBuffer = new int16_t[mBufferMask];
163 --mBufferMask;
164 mBufferHead = 0;
165 mBufferTail = 0;
166 mLatencyScore = 0;
167
168 // Initialize random bits.
169 read(gRandom, &mSequence, sizeof(mSequence));
170 read(gRandom, &mTimestamp, sizeof(mTimestamp));
171 read(gRandom, &mSsrc, sizeof(mSsrc));
172
173 mDtmfEvent = -1;
174 mDtmfStart = 0;
175
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800176 // Only take over these things when succeeded.
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800177 mSocket = socket;
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800178 if (codec) {
179 mRemote = *remote;
180 mCodec = codec;
181 }
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800182
183 LOGD("stream[%d] is configured as %s %dkHz %dms", mSocket,
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800184 (codec ? codec->name : "RAW"), mSampleRate, mInterval);
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800185 return true;
186}
187
188void AudioStream::sendDtmf(int event)
189{
190 if (mDtmfMagic != 0) {
191 mDtmfEvent = event << 24;
192 mDtmfStart = mTimestamp + mSampleCount;
193 }
194}
195
196bool AudioStream::mix(int32_t *output, int head, int tail, int sampleRate)
197{
198 if (mMode == SEND_ONLY) {
199 return false;
200 }
201
202 if (head - mBufferHead < 0) {
203 head = mBufferHead;
204 }
205 if (tail - mBufferTail > 0) {
206 tail = mBufferTail;
207 }
208 if (tail - head <= 0) {
209 return false;
210 }
211
212 head *= mSampleRate;
213 tail *= mSampleRate;
214
215 if (sampleRate == mSampleRate) {
216 for (int i = head; i - tail < 0; ++i) {
217 output[i - head] += mBuffer[i & mBufferMask];
218 }
219 } else {
220 // TODO: implement resampling.
221 return false;
222 }
223 return true;
224}
225
226void AudioStream::encode(int tick, AudioStream *chain)
227{
228 if (tick - mTick >= mInterval) {
229 // We just missed the train. Pretend that packets in between are lost.
230 int skipped = (tick - mTick) / mInterval;
231 mTick += skipped * mInterval;
232 mSequence += skipped;
233 mTimestamp += skipped * mSampleCount;
234 LOGD("stream[%d] skips %d packets", mSocket, skipped);
235 }
236
237 tick = mTick;
238 mTick += mInterval;
239 ++mSequence;
240 mTimestamp += mSampleCount;
241
242 if (mMode == RECEIVE_ONLY) {
243 return;
244 }
245
246 // If there is an ongoing DTMF event, send it now.
247 if (mDtmfEvent != -1) {
248 int duration = mTimestamp - mDtmfStart;
249 // Make sure duration is reasonable.
250 if (duration >= 0 && duration < mSampleRate * 100) {
251 duration += mSampleCount;
252 int32_t buffer[4] = {
253 htonl(mDtmfMagic | mSequence),
254 htonl(mDtmfStart),
255 mSsrc,
256 htonl(mDtmfEvent | duration),
257 };
258 if (duration >= mSampleRate * 100) {
259 buffer[3] |= htonl(1 << 23);
260 mDtmfEvent = -1;
261 }
262 sendto(mSocket, buffer, sizeof(buffer), MSG_DONTWAIT,
263 (sockaddr *)&mRemote, sizeof(mRemote));
264 return;
265 }
266 mDtmfEvent = -1;
267 }
268
269 // It is time to mix streams.
270 bool mixed = false;
271 int32_t buffer[mSampleCount + 3];
272 memset(buffer, 0, sizeof(buffer));
273 while (chain) {
274 if (chain != this &&
275 chain->mix(buffer, tick - mInterval, tick, mSampleRate)) {
276 mixed = true;
277 }
278 chain = chain->mNext;
279 }
280 if (!mixed) {
281 LOGD("stream[%d] no data", mSocket);
282 return;
283 }
284
285 // Cook the packet and send it out.
286 int16_t samples[mSampleCount];
287 for (int i = 0; i < mSampleCount; ++i) {
288 int32_t sample = buffer[i];
289 if (sample < -32768) {
290 sample = -32768;
291 }
292 if (sample > 32767) {
293 sample = 32767;
294 }
295 samples[i] = sample;
296 }
297 if (!mCodec) {
298 // Special case for device stream.
299 send(mSocket, samples, sizeof(samples), MSG_DONTWAIT);
300 return;
301 }
302
303 buffer[0] = htonl(mCodecMagic | mSequence);
304 buffer[1] = htonl(mTimestamp);
305 buffer[2] = mSsrc;
306 int length = mCodec->encode(&buffer[3], samples);
307 if (length <= 0) {
308 LOGD("stream[%d] encoder error", mSocket);
309 return;
310 }
311 sendto(mSocket, buffer, length + 12, MSG_DONTWAIT, (sockaddr *)&mRemote,
312 sizeof(mRemote));
313}
314
315void AudioStream::decode(int tick)
316{
317 char c;
318 if (mMode == SEND_ONLY) {
319 recv(mSocket, &c, 1, MSG_DONTWAIT);
320 return;
321 }
322
323 // Make sure mBufferHead and mBufferTail are reasonable.
324 if ((unsigned int)(tick + 256 - mBufferHead) > 1024) {
325 mBufferHead = tick - 64;
326 mBufferTail = mBufferHead;
327 }
328
329 if (tick - mBufferHead > 64) {
330 // Throw away outdated samples.
331 mBufferHead = tick - 64;
332 if (mBufferTail - mBufferHead < 0) {
333 mBufferTail = mBufferHead;
334 }
335 }
336
337 if (mBufferTail - tick <= 80) {
338 mLatencyScore = tick;
339 } else if (tick - mLatencyScore >= 5000) {
340 // Reset the jitter buffer to 40ms if the latency keeps larger than 80ms
341 // in the past 5s. This rarely happens, so let us just keep it simple.
342 LOGD("stream[%d] latency control", mSocket);
343 mBufferTail = tick + 40;
344 }
345
346 if (mBufferTail - mBufferHead > 256 - mInterval) {
347 // Buffer overflow. Drop the packet.
348 LOGD("stream[%d] buffer overflow", mSocket);
349 recv(mSocket, &c, 1, MSG_DONTWAIT);
350 return;
351 }
352
353 // Receive the packet and decode it.
354 int16_t samples[mSampleCount];
355 int length = 0;
356 if (!mCodec) {
357 // Special case for device stream.
358 length = recv(mSocket, samples, sizeof(samples),
359 MSG_TRUNC | MSG_DONTWAIT) >> 1;
360 } else {
361 __attribute__((aligned(4))) uint8_t buffer[2048];
362 length = recv(mSocket, buffer, sizeof(buffer),
363 MSG_TRUNC | MSG_DONTWAIT);
364
365 // Do we need to check SSRC, sequence, and timestamp? They are not
Chia-chi Yehb8790322010-08-19 18:26:53 +0800366 // reliable but at least they can be used to identify duplicates?
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800367 if (length < 12 || length > (int)sizeof(buffer) ||
368 (ntohl(*(uint32_t *)buffer) & 0xC07F0000) != mCodecMagic) {
369 LOGD("stream[%d] malformed packet", mSocket);
370 return;
371 }
372 int offset = 12 + ((buffer[0] & 0x0F) << 2);
373 if ((buffer[0] & 0x10) != 0) {
374 offset += 4 + (ntohs(*(uint16_t *)&buffer[offset + 2]) << 2);
375 }
376 if ((buffer[0] & 0x20) != 0) {
377 length -= buffer[length - 1];
378 }
379 length -= offset;
380 if (length >= 0) {
381 length = mCodec->decode(samples, &buffer[offset], length);
382 }
383 }
384 if (length != mSampleCount) {
385 LOGD("stream[%d] decoder error", mSocket);
386 return;
387 }
388
389 if (tick - mBufferTail > 0) {
390 // Buffer underrun. Reset the jitter buffer to 40ms.
391 LOGD("stream[%d] buffer underrun", mSocket);
392 if (mBufferTail - mBufferHead <= 0) {
393 mBufferHead = tick + 40;
394 mBufferTail = mBufferHead;
395 } else {
396 int tail = (tick + 40) * mSampleRate;
397 for (int i = mBufferTail * mSampleRate; i - tail < 0; ++i) {
398 mBuffer[i & mBufferMask] = 0;
399 }
400 mBufferTail = tick + 40;
401 }
402 }
403
404 // Append to the jitter buffer.
405 int tail = mBufferTail * mSampleRate;
406 for (int i = 0; i < mSampleCount; ++i) {
407 mBuffer[tail & mBufferMask] = samples[i];
408 ++tail;
409 }
410 mBufferTail += mInterval;
411}
412
413//------------------------------------------------------------------------------
414
415class AudioGroup
416{
417public:
418 AudioGroup();
419 ~AudioGroup();
420 bool set(int sampleRate, int sampleCount);
421
422 bool setMode(int mode);
423 bool sendDtmf(int event);
424 bool add(AudioStream *stream);
425 bool remove(int socket);
426
427private:
428 enum {
429 ON_HOLD = 0,
430 MUTED = 1,
431 NORMAL = 2,
432 EC_ENABLED = 3,
433 LAST_MODE = 3,
434 };
435 int mMode;
436 AudioStream *mChain;
437 int mEventQueue;
438 volatile int mDtmfEvent;
439
440 int mSampleCount;
441 int mDeviceSocket;
442 AudioTrack mTrack;
443 AudioRecord mRecord;
444
445 bool networkLoop();
446 bool deviceLoop();
447
448 class NetworkThread : public Thread
449 {
450 public:
451 NetworkThread(AudioGroup *group) : Thread(false), mGroup(group) {}
452
453 bool start()
454 {
455 if (run("Network", ANDROID_PRIORITY_AUDIO) != NO_ERROR) {
456 LOGE("cannot start network thread");
457 return false;
458 }
459 return true;
460 }
461
462 private:
463 AudioGroup *mGroup;
464 bool threadLoop()
465 {
466 return mGroup->networkLoop();
467 }
468 };
469 sp<NetworkThread> mNetworkThread;
470
471 class DeviceThread : public Thread
472 {
473 public:
474 DeviceThread(AudioGroup *group) : Thread(false), mGroup(group) {}
475
476 bool start()
477 {
478 char c;
479 while (recv(mGroup->mDeviceSocket, &c, 1, MSG_DONTWAIT) == 1);
480
481 if (run("Device", ANDROID_PRIORITY_AUDIO) != NO_ERROR) {
482 LOGE("cannot start device thread");
483 return false;
484 }
485 return true;
486 }
487
488 private:
489 AudioGroup *mGroup;
490 bool threadLoop()
491 {
492 return mGroup->deviceLoop();
493 }
494 };
495 sp<DeviceThread> mDeviceThread;
496};
497
498AudioGroup::AudioGroup()
499{
500 mMode = ON_HOLD;
501 mChain = NULL;
502 mEventQueue = -1;
503 mDtmfEvent = -1;
504 mDeviceSocket = -1;
505 mNetworkThread = new NetworkThread(this);
506 mDeviceThread = new DeviceThread(this);
507}
508
509AudioGroup::~AudioGroup()
510{
511 mNetworkThread->requestExitAndWait();
512 mDeviceThread->requestExitAndWait();
513 mTrack.stop();
514 mRecord.stop();
515 close(mEventQueue);
516 close(mDeviceSocket);
517 while (mChain) {
518 AudioStream *next = mChain->mNext;
519 delete mChain;
520 mChain = next;
521 }
522 LOGD("group[%d] is dead", mDeviceSocket);
523}
524
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800525bool AudioGroup::set(int sampleRate, int sampleCount)
526{
527 mEventQueue = epoll_create(2);
528 if (mEventQueue == -1) {
529 LOGE("epoll_create: %s", strerror(errno));
530 return false;
531 }
532
533 mSampleCount = sampleCount;
534
535 // Find out the frame count for AudioTrack and AudioRecord.
536 int output = 0;
537 int input = 0;
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800538 if (AudioTrack::getMinFrameCount(&output, AudioSystem::VOICE_CALL,
539 sampleRate) != NO_ERROR || output <= 0 ||
540 AudioRecord::getMinFrameCount(&input, sampleRate,
541 AudioSystem::PCM_16_BIT, 1) != NO_ERROR || input <= 0) {
542 LOGE("cannot compute frame count");
543 return false;
544 }
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800545 LOGD("reported frame count: output %d, input %d", output, input);
546
Chia-chi Yeh2880ef82010-08-24 13:58:12 +0800547 if (output < sampleCount * 2) {
548 output = sampleCount * 2;
549 }
550 if (input < sampleCount * 2) {
551 input = sampleCount * 2;
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800552 }
553 LOGD("adjusted frame count: output %d, input %d", output, input);
554
555 // Initialize AudioTrack and AudioRecord.
556 if (mTrack.set(AudioSystem::VOICE_CALL, sampleRate, AudioSystem::PCM_16_BIT,
557 AudioSystem::CHANNEL_OUT_MONO, output) != NO_ERROR ||
558 mRecord.set(AUDIO_SOURCE_MIC, sampleRate, AudioSystem::PCM_16_BIT,
559 AudioSystem::CHANNEL_IN_MONO, input) != NO_ERROR) {
560 LOGE("cannot initialize audio device");
561 return false;
562 }
563 LOGD("latency: output %d, input %d", mTrack.latency(), mRecord.latency());
564
Chia-chi Yeh7fa7ee12010-08-26 10:33:09 +0800565 // TODO: initialize echo canceler here.
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800566
567 // Create device socket.
568 int pair[2];
569 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair)) {
570 LOGE("socketpair: %s", strerror(errno));
571 return false;
572 }
573 mDeviceSocket = pair[0];
574
575 // Create device stream.
576 mChain = new AudioStream;
577 if (!mChain->set(AudioStream::NORMAL, pair[1], NULL, NULL,
578 sampleRate, sampleCount, -1, -1)) {
579 close(pair[1]);
580 LOGE("cannot initialize device stream");
581 return false;
582 }
583
584 // Give device socket a reasonable timeout and buffer size.
585 timeval tv;
586 tv.tv_sec = 0;
Chia-chi Yeh557b04d2010-09-08 09:56:02 +0800587 tv.tv_usec = 1000 * sampleCount / sampleRate * 500;
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800588 if (setsockopt(pair[0], SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) ||
589 setsockopt(pair[0], SOL_SOCKET, SO_RCVBUF, &output, sizeof(output)) ||
590 setsockopt(pair[1], SOL_SOCKET, SO_SNDBUF, &output, sizeof(output))) {
591 LOGE("setsockopt: %s", strerror(errno));
592 return false;
593 }
594
595 // Add device stream into event queue.
596 epoll_event event;
597 event.events = EPOLLIN;
598 event.data.ptr = mChain;
599 if (epoll_ctl(mEventQueue, EPOLL_CTL_ADD, pair[1], &event)) {
600 LOGE("epoll_ctl: %s", strerror(errno));
601 return false;
602 }
603
604 // Anything else?
605 LOGD("stream[%d] joins group[%d]", pair[1], pair[0]);
606 return true;
607}
608
609bool AudioGroup::setMode(int mode)
610{
611 if (mode < 0 || mode > LAST_MODE) {
612 return false;
613 }
614 if (mMode == mode) {
615 return true;
616 }
617
618 LOGD("group[%d] switches from mode %d to %d", mDeviceSocket, mMode, mode);
619 mMode = mode;
620
621 mDeviceThread->requestExitAndWait();
622 if (mode == ON_HOLD) {
623 mTrack.stop();
624 mRecord.stop();
625 return true;
626 }
627
628 mTrack.start();
629 if (mode == MUTED) {
630 mRecord.stop();
631 } else {
632 mRecord.start();
633 }
634
635 if (!mDeviceThread->start()) {
636 mTrack.stop();
637 mRecord.stop();
638 return false;
639 }
640 return true;
641}
642
643bool AudioGroup::sendDtmf(int event)
644{
645 if (event < 0 || event > 15) {
646 return false;
647 }
648
649 // DTMF is rarely used, so we try to make it as lightweight as possible.
650 // Using volatile might be dodgy, but using a pipe or pthread primitives
651 // or stop-set-restart threads seems too heavy. Will investigate later.
652 timespec ts;
653 ts.tv_sec = 0;
654 ts.tv_nsec = 100000000;
655 for (int i = 0; mDtmfEvent != -1 && i < 20; ++i) {
656 nanosleep(&ts, NULL);
657 }
658 if (mDtmfEvent != -1) {
659 return false;
660 }
661 mDtmfEvent = event;
662 nanosleep(&ts, NULL);
663 return true;
664}
665
666bool AudioGroup::add(AudioStream *stream)
667{
668 mNetworkThread->requestExitAndWait();
669
670 epoll_event event;
671 event.events = EPOLLIN;
672 event.data.ptr = stream;
673 if (epoll_ctl(mEventQueue, EPOLL_CTL_ADD, stream->mSocket, &event)) {
674 LOGE("epoll_ctl: %s", strerror(errno));
675 return false;
676 }
677
678 stream->mNext = mChain->mNext;
679 mChain->mNext = stream;
680 if (!mNetworkThread->start()) {
681 // Only take over the stream when succeeded.
682 mChain->mNext = stream->mNext;
683 return false;
684 }
685
686 LOGD("stream[%d] joins group[%d]", stream->mSocket, mDeviceSocket);
687 return true;
688}
689
690bool AudioGroup::remove(int socket)
691{
692 mNetworkThread->requestExitAndWait();
693
694 for (AudioStream *stream = mChain; stream->mNext; stream = stream->mNext) {
695 AudioStream *target = stream->mNext;
696 if (target->mSocket == socket) {
Chia-chi Yehb8790322010-08-19 18:26:53 +0800697 if (epoll_ctl(mEventQueue, EPOLL_CTL_DEL, socket, NULL)) {
698 LOGE("epoll_ctl: %s", strerror(errno));
699 return false;
700 }
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800701 stream->mNext = target->mNext;
702 LOGD("stream[%d] leaves group[%d]", socket, mDeviceSocket);
703 delete target;
704 break;
705 }
706 }
707
708 // Do not start network thread if there is only one stream.
709 if (!mChain->mNext || !mNetworkThread->start()) {
710 return false;
711 }
712 return true;
713}
714
715bool AudioGroup::networkLoop()
716{
717 int tick = elapsedRealtime();
718 int deadline = tick + 10;
719 int count = 0;
720
721 for (AudioStream *stream = mChain; stream; stream = stream->mNext) {
722 if (!stream->mTick || tick - stream->mTick >= 0) {
723 stream->encode(tick, mChain);
724 }
725 if (deadline - stream->mTick > 0) {
726 deadline = stream->mTick;
727 }
728 ++count;
729 }
730
731 if (mDtmfEvent != -1) {
732 int event = mDtmfEvent;
733 for (AudioStream *stream = mChain; stream; stream = stream->mNext) {
734 stream->sendDtmf(event);
735 }
736 mDtmfEvent = -1;
737 }
738
739 deadline -= tick;
740 if (deadline < 1) {
741 deadline = 1;
742 }
743
744 epoll_event events[count];
745 count = epoll_wait(mEventQueue, events, count, deadline);
746 if (count == -1) {
747 LOGE("epoll_wait: %s", strerror(errno));
748 return false;
749 }
750 for (int i = 0; i < count; ++i) {
751 ((AudioStream *)events[i].data.ptr)->decode(tick);
752 }
753
754 return true;
755}
756
757bool AudioGroup::deviceLoop()
758{
759 int16_t output[mSampleCount];
760
761 if (recv(mDeviceSocket, output, sizeof(output), 0) <= 0) {
762 memset(output, 0, sizeof(output));
763 }
Chia-chi Yeh2880ef82010-08-24 13:58:12 +0800764
765 int16_t input[mSampleCount];
766 int toWrite = mSampleCount;
767 int toRead = (mMode == MUTED) ? 0 : mSampleCount;
768 int chances = 100;
769
770 while (--chances > 0 && (toWrite > 0 || toRead > 0)) {
771 if (toWrite > 0) {
772 AudioTrack::Buffer buffer;
773 buffer.frameCount = toWrite;
774
775 status_t status = mTrack.obtainBuffer(&buffer, 1);
776 if (status == NO_ERROR) {
777 memcpy(buffer.i8, &output[mSampleCount - toWrite], buffer.size);
778 toWrite -= buffer.frameCount;
779 mTrack.releaseBuffer(&buffer);
780 } else if (status != TIMED_OUT && status != WOULD_BLOCK) {
781 LOGE("cannot write to AudioTrack");
782 return false;
783 }
784 }
785
786 if (toRead > 0) {
787 AudioRecord::Buffer buffer;
788 buffer.frameCount = mRecord.frameCount();
789
790 status_t status = mRecord.obtainBuffer(&buffer, 1);
791 if (status == NO_ERROR) {
Chia-chi Yeh557b04d2010-09-08 09:56:02 +0800792 int count = ((int)buffer.frameCount < toRead) ?
Chia-chi Yeh2880ef82010-08-24 13:58:12 +0800793 buffer.frameCount : toRead;
794 memcpy(&input[mSampleCount - toRead], buffer.i8, count * 2);
795 toRead -= count;
796 if (buffer.frameCount < mRecord.frameCount()) {
797 buffer.frameCount = count;
798 }
799 mRecord.releaseBuffer(&buffer);
800 } else if (status != TIMED_OUT && status != WOULD_BLOCK) {
801 LOGE("cannot read from AudioRecord");
802 return false;
803 }
804 }
805 }
806
807 if (!chances) {
808 LOGE("device loop timeout");
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800809 return false;
810 }
811
812 if (mMode != MUTED) {
Chia-chi Yeh2880ef82010-08-24 13:58:12 +0800813 if (mMode == NORMAL) {
814 send(mDeviceSocket, input, sizeof(input), MSG_DONTWAIT);
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800815 } else {
Chia-chi Yeh7fa7ee12010-08-26 10:33:09 +0800816 // TODO: Echo canceller runs here.
817 send(mDeviceSocket, input, sizeof(input), MSG_DONTWAIT);
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800818 }
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800819 }
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800820 return true;
821}
822
823//------------------------------------------------------------------------------
824
825static jfieldID gNative;
826static jfieldID gMode;
827
Chia-chi Yehb8790322010-08-19 18:26:53 +0800828void add(JNIEnv *env, jobject thiz, jint mode,
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800829 jint socket, jstring jRemoteAddress, jint remotePort,
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800830 jstring jCodecSpec, jint dtmfType)
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800831{
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800832 AudioCodec *codec = NULL;
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800833 AudioStream *stream = NULL;
834 AudioGroup *group = NULL;
835
836 // Sanity check.
837 sockaddr_storage remote;
838 if (parse(env, jRemoteAddress, remotePort, &remote) < 0) {
839 // Exception already thrown.
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800840 return;
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800841 }
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800842 if (!jCodecSpec) {
843 jniThrowNullPointerException(env, "codecSpec");
844 return;
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800845 }
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800846 const char *codecSpec = env->GetStringUTFChars(jCodecSpec, NULL);
847 if (!codecSpec) {
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800848 // Exception already thrown.
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800849 return;
850 }
851
852 // Create audio codec.
853 int codecType = -1;
854 char codecName[16];
855 int sampleRate = -1;
856 sscanf(codecSpec, "%d %[^/]%*c%d", &codecType, codecName, &sampleRate);
857 codec = newAudioCodec(codecName);
858 int sampleCount = (codec ? codec->set(sampleRate, codecSpec) : -1);
859 env->ReleaseStringUTFChars(jCodecSpec, codecSpec);
860 if (sampleCount <= 0) {
861 jniThrowException(env, "java/lang/IllegalStateException",
862 "cannot initialize audio codec");
Chia-chi Yehb8790322010-08-19 18:26:53 +0800863 goto error;
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800864 }
865
866 // Create audio stream.
867 stream = new AudioStream;
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800868 if (!stream->set(mode, socket, &remote, codec, sampleRate, sampleCount,
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800869 codecType, dtmfType)) {
870 jniThrowException(env, "java/lang/IllegalStateException",
871 "cannot initialize audio stream");
872 goto error;
873 }
874 socket = -1;
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800875 codec = NULL;
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800876
877 // Create audio group.
878 group = (AudioGroup *)env->GetIntField(thiz, gNative);
879 if (!group) {
880 int mode = env->GetIntField(thiz, gMode);
881 group = new AudioGroup;
882 if (!group->set(8000, 256) || !group->setMode(mode)) {
883 jniThrowException(env, "java/lang/IllegalStateException",
884 "cannot initialize audio group");
885 goto error;
886 }
887 }
888
889 // Add audio stream into audio group.
890 if (!group->add(stream)) {
891 jniThrowException(env, "java/lang/IllegalStateException",
892 "cannot add audio stream");
893 goto error;
894 }
895
896 // Succeed.
897 env->SetIntField(thiz, gNative, (int)group);
Chia-chi Yehb8790322010-08-19 18:26:53 +0800898 return;
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800899
900error:
901 delete group;
902 delete stream;
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800903 delete codec;
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800904 close(socket);
905 env->SetIntField(thiz, gNative, NULL);
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800906}
907
908void remove(JNIEnv *env, jobject thiz, jint socket)
909{
910 AudioGroup *group = (AudioGroup *)env->GetIntField(thiz, gNative);
911 if (group) {
912 if (socket == -1 || !group->remove(socket)) {
913 delete group;
914 env->SetIntField(thiz, gNative, NULL);
915 }
916 }
917}
918
919void setMode(JNIEnv *env, jobject thiz, jint mode)
920{
921 AudioGroup *group = (AudioGroup *)env->GetIntField(thiz, gNative);
922 if (group && !group->setMode(mode)) {
923 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
924 return;
925 }
926 env->SetIntField(thiz, gMode, mode);
927}
928
929void sendDtmf(JNIEnv *env, jobject thiz, jint event)
930{
931 AudioGroup *group = (AudioGroup *)env->GetIntField(thiz, gNative);
932 if (group && !group->sendDtmf(event)) {
933 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
934 }
935}
936
937JNINativeMethod gMethods[] = {
Chia-chi Yeh4033a672010-09-16 18:36:45 +0800938 {"add", "(IILjava/lang/String;ILjava/lang/String;I)V", (void *)add},
Chia-chi Yeh4c5d28c2010-08-06 14:12:05 +0800939 {"remove", "(I)V", (void *)remove},
940 {"setMode", "(I)V", (void *)setMode},
941 {"sendDtmf", "(I)V", (void *)sendDtmf},
942};
943
944} // namespace
945
946int registerAudioGroup(JNIEnv *env)
947{
948 gRandom = open("/dev/urandom", O_RDONLY);
949 if (gRandom == -1) {
950 LOGE("urandom: %s", strerror(errno));
951 return -1;
952 }
953
954 jclass clazz;
955 if ((clazz = env->FindClass("android/net/rtp/AudioGroup")) == NULL ||
956 (gNative = env->GetFieldID(clazz, "mNative", "I")) == NULL ||
957 (gMode = env->GetFieldID(clazz, "mMode", "I")) == NULL ||
958 env->RegisterNatives(clazz, gMethods, NELEM(gMethods)) < 0) {
959 LOGE("JNI registration failed");
960 return -1;
961 }
962 return 0;
963}