• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 // FIXME taken from OpenSLES_AndroidConfiguration.h
18 #define SL_ANDROID_KEY_PERFORMANCE_MODE  ((const SLchar*) "androidPerformanceMode")
19 
20 ////////////////////////////////////////////
21 /// Actual sles functions.
22 
23 
24 // Test program to record from default audio input and playback to default audio output.
25 // It will generate feedback (Larsen effect) if played through on-device speakers,
26 // or acts as a delay if played through headset.
27 
28 #define _USE_MATH_DEFINES
29 #include <cmath>
30 #include "sles.h"
31 #include "audio_utils/atomic.h"
32 #include "byte_buffer.h"
33 #include <unistd.h>
34 #include <string.h>
35 
36 static int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount, int micSource,
37         int performanceMode,
38         int testType, double frequency1, char* byteBufferPtr, int byteBufferLength,
39         short* loopbackTone, int maxRecordedLateCallbacks, int ignoreFirstFrames);
40 static int slesDestroyServer(sles_data *pSles);
41 
42 static void initBufferStats(bufferStats *stats);
43 static void collectBufferPeriod(bufferStats *stats, bufferStats *fdpStats,
44         callbackTimeStamps *timeStamps, short expectedBufferPeriod);
45 static bool updateBufferStats(bufferStats *stats, int64_t diff_in_nano, int expectedBufferPeriod);
46 static void recordTimeStamp(callbackTimeStamps *timeStamps,
47         int64_t callbackDuration, int64_t timeStamp);
48 
slesComputeDefaultSettings(int,int *,int *,int *)49 int slesComputeDefaultSettings(int /*performanceMode*/, int* /*samplingRate*/,
50             int* /*playerBufferFrameCount*/, int* /*recorderBufferFrameCount*/) {
51     // For OpenSL ES, these parameters can be determined by NativeAudioThread itself.
52     return STATUS_FAIL;
53 }
54 
slesInit(void ** ppCtx,int samplingRate,int frameCount,int micSource,int performanceMode,int testType,double frequency1,char * byteBufferPtr,int byteBufferLength,short * loopbackTone,int maxRecordedLateCallbacks,int ignoreFirstFrames)55 int slesInit(void ** ppCtx, int samplingRate, int frameCount, int micSource,
56              int performanceMode,
57              int testType, double frequency1, char* byteBufferPtr, int byteBufferLength,
58              short* loopbackTone, int maxRecordedLateCallbacks, int ignoreFirstFrames) {
59     sles_data ** ppSles = (sles_data**) ppCtx;
60     int status = STATUS_FAIL;
61     if (ppSles != NULL) {
62         sles_data * pSles = (sles_data*) calloc(1, sizeof(sles_data));
63 
64         SLES_PRINTF("pSles malloc %zu bytes at %p", sizeof(sles_data), pSles);
65         //__android_log_print(ANDROID_LOG_INFO, "sles_jni",
66         //"malloc %d bytes at %p", sizeof(sles_data), pSles);//Or ANDROID_LOG_INFO, ...
67         *ppSles = pSles;
68         if (pSles != NULL)
69         {
70             SLES_PRINTF("creating server. Sampling rate =%d, frame count = %d",
71                         samplingRate, frameCount);
72             status = slesCreateServer(pSles, samplingRate, frameCount, micSource,
73                                       performanceMode, testType,
74                                       frequency1, byteBufferPtr, byteBufferLength, loopbackTone,
75                                       maxRecordedLateCallbacks, ignoreFirstFrames);
76             SLES_PRINTF("slesCreateServer =%d", status);
77         }
78     }
79 
80     return status;
81 }
slesDestroy(void ** ppCtx)82 int slesDestroy(void ** ppCtx) {
83     sles_data ** ppSles = (sles_data**)ppCtx;
84     int status = STATUS_FAIL;
85     if (ppSles != NULL) {
86         slesDestroyServer(*ppSles);
87 
88         if (*ppSles != NULL)
89         {
90             SLES_PRINTF("free memory at %p",*ppSles);
91             free(*ppSles);
92             *ppSles = 0;
93         }
94         status = STATUS_SUCCESS;
95     }
96     return status;
97 }
98 
99 #define ASSERT(x) do { if(!(x)) { __android_log_assert("assert", "sles_jni", \
100                     "ASSERTION FAILED: " #x); } } while (0)
101 #define ASSERT_EQ(x, y) do { if ((x) == (y)) ; else __android_log_assert("assert", "sles_jni", \
102                     "ASSERTION FAILED: 0x%x != 0x%x\n", (unsigned) (x), (unsigned) (y)); } while (0)
103 
104 // Called after audio recorder fills a buffer with data, then we can read from this filled buffer
recorderCallback(SLAndroidSimpleBufferQueueItf caller __unused,void * context)105 static void recorderCallback(SLAndroidSimpleBufferQueueItf caller __unused, void *context) {
106     sles_data *pSles = (sles_data*) context;
107     if (pSles != NULL) {
108         collectBufferPeriod(&pSles->recorderBufferStats, NULL /*fdpStats*/,
109                             &pSles->recorderTimeStamps, pSles->expectedBufferPeriod);
110 
111         //__android_log_print(ANDROID_LOG_INFO, "sles_jni", "in recorderCallback");
112         SLresult result;
113 
114         //ee  SLES_PRINTF("<R");
115 
116         // We should only be called when a recording buffer is done
117         ASSERT(pSles->rxFront <= pSles->rxBufCount);
118         ASSERT(pSles->rxRear <= pSles->rxBufCount);
119         ASSERT(pSles->rxFront != pSles->rxRear);
120         char *buffer = pSles->rxBuffers[pSles->rxFront]; //pSles->rxBuffers stores the data recorded
121 
122 
123         // Remove buffer from record queue
124         if (++pSles->rxFront > pSles->rxBufCount) {
125             pSles->rxFront = 0;
126         }
127 
128         if (pSles->testType == TEST_TYPE_LATENCY) {
129             // Throw out first frames
130             if (pSles->ignoreFirstFrames) {
131                 int framesToErase = pSles->ignoreFirstFrames;
132                 if (framesToErase > (int) pSles->bufSizeInFrames) {
133                     framesToErase = pSles->bufSizeInFrames;
134                 }
135                 pSles->ignoreFirstFrames -= framesToErase;
136                 memset(buffer, 0, framesToErase * pSles->channels * sizeof(short));
137             }
138 
139             ssize_t actual = audio_utils_fifo_write(&(pSles->fifo), buffer,
140                     (size_t) pSles->bufSizeInFrames);
141 
142             if (actual != (ssize_t) pSles->bufSizeInFrames) {
143                 write(1, "?", 1);
144             }
145 
146             // This is called by a realtime (SCHED_FIFO) thread,
147             // and it is unsafe to do I/O as it could block for unbounded time.
148             // Flash filesystem is especially notorious for blocking.
149             if (pSles->fifo2Buffer != NULL) {
150                 actual = audio_utils_fifo_write(&(pSles->fifo2), buffer,
151                         (size_t) pSles->bufSizeInFrames);
152                 if (actual != (ssize_t) pSles->bufSizeInFrames) {
153                     write(1, "?", 1);
154                 }
155             }
156         } else if (pSles->testType == TEST_TYPE_BUFFER_PERIOD) {
157             if (pSles->fifo2Buffer != NULL) {
158                 ssize_t actual = byteBuffer_write(pSles->byteBufferPtr, pSles->byteBufferLength,
159                         buffer, (size_t) pSles->bufSizeInFrames, pSles->channels);
160 
161                 //FIXME should log errors using other methods instead of printing to terminal
162                 if (actual != (ssize_t) pSles->bufSizeInFrames) {
163                     write(1, "?", 1);
164                 }
165             }
166         }
167 
168 
169         // Enqueue this same buffer for the recorder to fill again.
170         result = (*(pSles->recorderBufferQueue))->Enqueue(pSles->recorderBufferQueue, buffer,
171                                                           pSles->bufSizeInBytes);
172         //__android_log_print(ANDROID_LOG_INFO, "recorderCallback", "recorder buffer size: %i",
173         //                    pSles->bufSizeInBytes);
174         ASSERT_EQ(SL_RESULT_SUCCESS, result);
175 
176 
177         // Update our model of the record queue
178         SLuint32 rxRearNext = pSles->rxRear + 1;
179         if (rxRearNext > pSles->rxBufCount) {
180             rxRearNext = 0;
181         }
182         ASSERT(rxRearNext != pSles->rxFront);
183         pSles->rxBuffers[pSles->rxRear] = buffer;
184         pSles->rxRear = rxRearNext;
185 
186 
187 
188       //ee  SLES_PRINTF("r>");
189 
190     } //pSles not null
191 }
192 
193 
194 // Calculate nanosecond difference between two timespec structs from clock_gettime(CLOCK_MONOTONIC)
195 // tv_sec [0, max time_t] , tv_nsec [0, 999999999]
diffInNano(struct timespec previousTime,struct timespec currentTime)196 static int64_t diffInNano(struct timespec previousTime, struct timespec currentTime) {
197     return (int64_t) (currentTime.tv_sec - previousTime.tv_sec) * (int64_t) NANOS_PER_SECOND +
198             currentTime.tv_nsec - previousTime.tv_nsec;
199 }
200 
201 // Called after audio player empties a buffer of data
playerCallback(SLBufferQueueItf caller __unused,void * context)202 static void playerCallback(SLBufferQueueItf caller __unused, void *context) {
203     sles_data *pSles = (sles_data*) context;
204     if (pSles != NULL) {
205         collectBufferPeriod(&pSles->playerBufferStats, &pSles->recorderBufferStats /*fdpStats*/,
206                             &pSles->playerTimeStamps, pSles->expectedBufferPeriod);
207         SLresult result;
208 
209         //ee  SLES_PRINTF("<P");
210 
211         // Get the buffer that just finished playing
212         ASSERT(pSles->txFront <= pSles->txBufCount);
213         ASSERT(pSles->txRear <= pSles->txBufCount);
214         ASSERT(pSles->txFront != pSles->txRear);
215         char *buffer = pSles->txBuffers[pSles->txFront];
216         if (++pSles->txFront > pSles->txBufCount) {
217             pSles->txFront = 0;
218         }
219 
220         if (pSles->testType == TEST_TYPE_LATENCY) {
221             // Jitter buffer should have strictly less than 2 buffers worth of data in it.
222             // This is to prevent the test itself from adding too much latency.
223             size_t discardedInputFrames = 0;
224             for (;;) {
225                 size_t availToRead = audio_utils_fifo_availToRead(&pSles->fifo);
226                 if (availToRead < pSles->bufSizeInFrames * 2) {
227                     break;
228                 }
229                 ssize_t actual = audio_utils_fifo_read(&pSles->fifo, buffer,
230                         pSles->bufSizeInFrames);
231                 if (actual > 0) {
232                     discardedInputFrames += actual;
233                 }
234                 if (actual != (ssize_t) pSles->bufSizeInFrames) {
235                     break;
236                 }
237             }
238             if (discardedInputFrames > 0) {
239                 if (pSles->totalDiscardedInputFrames > 0) {
240                     __android_log_print(ANDROID_LOG_WARN, "sles_jni",
241                         "Discarded an additional %zu input frames after a total of %zu input frames"
242                         " had previously been discarded",
243                         discardedInputFrames, pSles->totalDiscardedInputFrames);
244                 }
245                 pSles->totalDiscardedInputFrames += discardedInputFrames;
246             }
247 
248             ssize_t actual = audio_utils_fifo_read(&(pSles->fifo), buffer, pSles->bufSizeInFrames);
249             if (actual != (ssize_t) pSles->bufSizeInFrames) {
250                 write(1, "/", 1);
251                 // on underrun from pipe, substitute silence
252                 memset(buffer, 0, pSles->bufSizeInFrames * pSles->channels * sizeof(short));
253             }
254 
255             if (pSles->injectImpulse == -1) {   // here we inject pulse
256 
257                 /*// Experimentally, a single frame impulse was insufficient to trigger feedback.
258                 // Also a Nyquist frequency signal was also insufficient, probably because
259                 // the response of output and/or input path was not adequate at high frequencies.
260                 // This short burst of a few cycles of square wave at Nyquist/4 found to work well.
261                 for (unsigned i = 0; i < pSles->bufSizeInFrames / 8; i += 8) {
262                     for (int j = 0; j < 8; j++) {
263                         for (unsigned k = 0; k < pSles->channels; k++) {
264                             ((short *) buffer)[(i + j) * pSles->channels + k] =
265                                                                             j < 4 ? 0x7FFF : 0x8000;
266                         }
267                     }
268                 }*/
269 
270                 //inject java generated tone
271                 for (unsigned i = 0; i < pSles->bufSizeInFrames; ++i) {
272                     for (unsigned k = 0; k < pSles->channels; ++k) {
273                         ((short *) buffer)[i * pSles->channels + k] = pSles->loopbackTone[i];
274                     }
275                 }
276 
277                 pSles->injectImpulse = 0;
278                 pSles->totalDiscardedInputFrames = 0;
279             }
280         } else if (pSles->testType == TEST_TYPE_BUFFER_PERIOD) {
281             double twoPi = M_PI * 2;
282             int maxShort = 32767;
283             float amplitude = 0.8;
284             short value;
285             double phaseIncrement = pSles->frequency1 / pSles->sampleRate;
286             bool isGlitchEnabled = false;
287             for (unsigned i = 0; i < pSles->bufSizeInFrames; i++) {
288                 value = (short) (sin(pSles->bufferTestPhase1) * maxShort * amplitude);
289                 for (unsigned k = 0; k < pSles->channels; ++k) {
290                     ((short *) buffer)[i* pSles->channels + k] = value;
291                 }
292 
293                 pSles->bufferTestPhase1 += twoPi * phaseIncrement;
294                 // insert glitches if isGlitchEnabled == true, and insert it for every second
295                 if (isGlitchEnabled && (pSles->count % pSles->sampleRate == 0)) {
296                     pSles->bufferTestPhase1 += twoPi * phaseIncrement;
297                 }
298 
299                 pSles->count++;
300 
301                 while (pSles->bufferTestPhase1 > twoPi) {
302                     pSles->bufferTestPhase1 -= twoPi;
303                 }
304             }
305         }
306 
307         // Enqueue the filled buffer for playing
308         result = (*(pSles->playerBufferQueue))->Enqueue(pSles->playerBufferQueue, buffer,
309                                                         pSles->bufSizeInBytes);
310         ASSERT_EQ(SL_RESULT_SUCCESS, result);
311 
312         // Update our model of the player queue
313         ASSERT(pSles->txFront <= pSles->txBufCount);
314         ASSERT(pSles->txRear <= pSles->txBufCount);
315         SLuint32 txRearNext = pSles->txRear + 1;
316         if (txRearNext > pSles->txBufCount) {
317             txRearNext = 0;
318         }
319         ASSERT(txRearNext != pSles->txFront);
320         pSles->txBuffers[pSles->txRear] = buffer;
321         pSles->txRear = txRearNext;
322 
323     } //pSles not null
324 }
325 
326 // Used to set initial values for the bufferStats struct before values can be recorded.
initBufferStats(bufferStats * stats)327 static void initBufferStats(bufferStats *stats) {
328     stats->buffer_period = new int[RANGE](); // initialized to zeros
329     stats->previous_time = {0,0};
330     stats->current_time = {0,0};
331 
332     stats->buffer_count = 0;
333     stats->max_buffer_period = 0;
334 
335     stats->measurement_count = 0;
336     stats->SDM = 0;
337     stats->var = 0;
338 }
339 
340 // Called in the beginning of playerCallback() to collect the interval between each callback.
341 // fdpStats is either NULL or a pointer to the buffer statistics for the full-duplex partner.
collectBufferPeriod(bufferStats * stats,bufferStats * fdpStats,callbackTimeStamps * timeStamps,short expectedBufferPeriod)342 static void collectBufferPeriod(bufferStats *stats, bufferStats *fdpStats,
343         callbackTimeStamps *timeStamps, short expectedBufferPeriod) {
344     clock_gettime(CLOCK_MONOTONIC, &(stats->current_time));
345 
346     if (timeStamps->startTime.tv_sec == 0 && timeStamps->startTime.tv_nsec == 0) {
347         timeStamps->startTime = stats->current_time;
348     }
349 
350     (stats->buffer_count)++;
351 
352     if (stats->previous_time.tv_sec != 0 && stats->buffer_count > BUFFER_PERIOD_DISCARD &&
353          (fdpStats == NULL || fdpStats->buffer_count > BUFFER_PERIOD_DISCARD_FULL_DUPLEX_PARTNER)) {
354 
355         int64_t callbackDuration = diffInNano(stats->previous_time, stats->current_time);
356 
357         bool outlier = updateBufferStats(stats, callbackDuration, expectedBufferPeriod);
358 
359         //recording timestamps of buffer periods not at expected buffer period
360         if (outlier) {
361             int64_t timeStamp = diffInNano(timeStamps->startTime, stats->current_time);
362             recordTimeStamp(timeStamps, callbackDuration, timeStamp);
363         }
364     }
365 
366     stats->previous_time = stats->current_time;
367 }
368 
369 // Records an outlier given the duration in nanoseconds and the number of nanoseconds
370 // between it and the start of the test.
recordTimeStamp(callbackTimeStamps * timeStamps,int64_t callbackDuration,int64_t timeStamp)371 static void recordTimeStamp(callbackTimeStamps *timeStamps,
372         int64_t callbackDuration, int64_t timeStamp) {
373     if (timeStamps->exceededCapacity) {
374         return;
375     }
376 
377     //only marked as exceeded if attempting to record a late callback after arrays full
378     if (timeStamps->index == timeStamps->capacity){
379         timeStamps->exceededCapacity = true;
380     } else {
381         timeStamps->callbackDurations[timeStamps->index] =
382                 (short) ((callbackDuration + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI);
383         timeStamps->timeStampsMs[timeStamps->index] =
384                 (int) ((timeStamp + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI);
385         timeStamps->index++;
386     }
387 }
388 
atomicSetIfGreater(volatile int32_t * addr,int32_t val)389 static void atomicSetIfGreater(volatile int32_t *addr, int32_t val) {
390     // TODO: rewrite this to avoid the need for unbounded spinning
391     int32_t old;
392     do {
393         old = *addr;
394         if (val < old) return;
395     } while(!android_atomic_compare_exchange(&old, val, addr));
396 }
397 
398 // Updates the stats being collected about buffer periods. Returns true if this is an outlier.
updateBufferStats(bufferStats * stats,int64_t diff_in_nano,int expectedBufferPeriod)399 static bool updateBufferStats(bufferStats *stats, int64_t diff_in_nano, int expectedBufferPeriod) {
400     stats->measurement_count++;
401 
402     // round up to nearest millisecond
403     int diff_in_milli = (int) ((diff_in_nano + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI);
404 
405     if (diff_in_milli > stats->max_buffer_period) {
406         stats->max_buffer_period = diff_in_milli;
407     }
408 
409     // from 0 ms to 1000 ms, plus a sum of all instances > 1000ms
410     if (diff_in_milli >= (RANGE - 1)) {
411         (stats->buffer_period)[RANGE-1]++;
412     } else if (diff_in_milli >= 0) {
413         (stats->buffer_period)[diff_in_milli]++;
414     } else { // for diff_in_milli < 0
415         __android_log_print(ANDROID_LOG_INFO, "sles_player", "Having negative BufferPeriod.");
416     }
417 
418     int64_t delta = diff_in_nano - (int64_t) expectedBufferPeriod * NANOS_PER_MILLI;
419     stats->SDM += delta * delta;
420     if (stats->measurement_count > 1) {
421         stats->var = stats->SDM / stats->measurement_count;
422     }
423 
424     // check if the lateness is so bad that a systrace should be captured
425     // TODO: replace static threshold of lateness with a dynamic determination
426     if (diff_in_milli > expectedBufferPeriod + LATE_CALLBACK_CAPTURE_THRESHOLD) {
427         // TODO: log in a non-blocking way
428         //__android_log_print(ANDROID_LOG_INFO, "buffer_stats", "Callback late by %d ms",
429         //                    diff_in_milli - expectedBufferPeriod);
430         atomicSetIfGreater(&(stats->captureRank), diff_in_milli - expectedBufferPeriod);
431     }
432     return diff_in_milli > expectedBufferPeriod + LATE_CALLBACK_OUTLIER_THRESHOLD;
433 }
434 
slesCreateServer(sles_data * pSles,int samplingRate,int frameCount,int micSource,int performanceMode,int testType,double frequency1,char * byteBufferPtr,int byteBufferLength,short * loopbackTone,int maxRecordedLateCallbacks,int ignoreFirstFrames)435 static int slesCreateServer(sles_data *pSles, int samplingRate, int frameCount, int micSource,
436         int performanceMode,
437         int testType, double frequency1, char *byteBufferPtr, int byteBufferLength,
438         short *loopbackTone, int maxRecordedLateCallbacks, int ignoreFirstFrames) {
439     int status = STATUS_FAIL;
440 
441     if (pSles != NULL) {
442 
443         //        adb shell slesTest_feedback -r1 -t1 -s48000 -f240 -i300 -e3 -o/sdcard/log.wav
444         //            r1 and t1 are the receive and transmit buffer counts, typically 1
445         //            s is the sample rate, typically 48000 or 44100
446         //            f is the frame count per buffer, typically 240 or 256
447         //            i is the number of milliseconds before impulse.  You may need to adjust this.
448         //            e is number of seconds to record
449         //            o is output .wav file name
450 
451 
452         //        // default values
453         //        SLuint32 rxBufCount = 1;     // -r#
454         //        SLuint32 txBufCount = 1;     // -t#
455         //        SLuint32 bufSizeInFrames = 240;  // -f#
456         //        SLuint32 channels = 1;       // -c#
457         //        SLuint32 sampleRate = 48000; // -s#
458         //        SLuint32 exitAfterSeconds = 3; // -e#
459         //        SLuint32 freeBufCount = 0;   // calculated
460         //        SLuint32 bufSizeInBytes = 0; // calculated
461         //        int injectImpulse = 300; // -i#i
462         //
463         //        // Storage area for the buffer queues
464         //        char **rxBuffers;
465         //        char **txBuffers;
466         //        char **freeBuffers;
467         //
468         //        // Buffer indices
469         //        SLuint32 rxFront;    // oldest recording
470         //        SLuint32 rxRear;     // next to be recorded
471         //        SLuint32 txFront;    // oldest playing
472         //        SLuint32 txRear;     // next to be played
473         //        SLuint32 freeFront;  // oldest free
474         //        SLuint32 freeRear;   // next to be freed
475         //
476         //        audio_utils_fifo fifo; //(*)
477         //        SLAndroidSimpleBufferQueueItf recorderBufferQueue;
478         //        SLBufferQueueItf playerBufferQueue;
479 
480         // default values
481         pSles->rxBufCount = 1;     // -r#
482         pSles->txBufCount = 1;     // -t#
483         pSles->bufSizeInFrames = frameCount;//240;  // -f#
484         pSles->channels = 1;       // -c#
485         pSles->sampleRate = samplingRate;//48000; // -s#
486         pSles->exitAfterSeconds = 3; // -e#
487         pSles->freeBufCount = 0;   // calculated
488         pSles->bufSizeInBytes = 0; // calculated
489         pSles->injectImpulse = 300; // -i#i
490         pSles->totalDiscardedInputFrames = 0;
491         pSles->ignoreFirstFrames = ignoreFirstFrames;
492 
493         // Storage area for the buffer queues
494         //        char **rxBuffers;
495         //        char **txBuffers;
496         //        char **freeBuffers;
497 
498         // Buffer indices
499 #if 0
500         pSles->rxFront;    // oldest recording
501         pSles->rxRear;     // next to be recorded
502         pSles->txFront;    // oldest playing
503         pSles->txRear;     // next to be played
504         pSles->freeFront;  // oldest free
505         pSles->freeRear;   // next to be freed
506 
507         pSles->fifo; //(*)
508 #endif
509         pSles->fifo2Buffer = NULL;  //this fifo is for sending data to java code (to plot it)
510 #if 0
511         pSles->recorderBufferQueue;
512         pSles->playerBufferQueue;
513 #endif
514 
515 
516 
517         // compute total free buffers as -r plus -t
518         pSles->freeBufCount = pSles->rxBufCount + pSles->txBufCount;
519         // compute buffer size
520         pSles->bufSizeInBytes = pSles->channels * pSles->bufSizeInFrames * sizeof(short);
521 
522         // Initialize free buffers
523         pSles->freeBuffers = (char **) calloc(pSles->freeBufCount + 1, sizeof(char *));
524         SLES_PRINTF("  calloc freeBuffers %llu bytes at %p", (long long)pSles->freeBufCount + 1,
525                     pSles->freeBuffers);
526         unsigned j;
527         for (j = 0; j < pSles->freeBufCount; ++j) {
528             pSles->freeBuffers[j] = (char *) malloc(pSles->bufSizeInBytes);
529             SLES_PRINTF(" buff%d malloc %llu bytes at %p",j, (long long)pSles->bufSizeInBytes,
530                         pSles->freeBuffers[j]);
531         }
532         pSles->freeFront = 0;
533         pSles->freeRear = pSles->freeBufCount;
534         pSles->freeBuffers[j] = NULL;
535 
536         // Initialize record queue
537         pSles->rxBuffers = (char **) calloc(pSles->rxBufCount + 1, sizeof(char *));
538         SLES_PRINTF("  calloc rxBuffers %llu bytes at %p", (long long)pSles->rxBufCount + 1,
539                 pSles->rxBuffers);
540         pSles->rxFront = 0;
541         pSles->rxRear = 0;
542 
543         // Initialize play queue
544         pSles->txBuffers = (char **) calloc(pSles->txBufCount + 1, sizeof(char *));
545         SLES_PRINTF("  calloc txBuffers %llu bytes at %p", (long long)pSles->txBufCount + 1,
546                 pSles->txBuffers);
547         pSles->txFront = 0;
548         pSles->txRear = 0;
549 
550         size_t frameSize = pSles->channels * sizeof(short);
551 #define FIFO_FRAMES 1024
552         pSles->fifoBuffer = new short[FIFO_FRAMES * pSles->channels];
553         audio_utils_fifo_init(&(pSles->fifo), FIFO_FRAMES, frameSize, pSles->fifoBuffer);
554 
555         //        SNDFILE *sndfile;
556         //        if (outFileName != NULL) {
557         // create .wav writer
558         //            SF_INFO info;
559         //            info.frames = 0;
560         //            info.samplerate = sampleRate;
561         //            info.channels = channels;
562         //            info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
563         //            sndfile = sf_open(outFileName, SFM_WRITE, &info);
564         //            if (sndfile != NULL) {
565 #define FIFO2_FRAMES 65536
566         pSles->fifo2Buffer = new short[FIFO2_FRAMES * pSles->channels];
567         audio_utils_fifo_init(&(pSles->fifo2), FIFO2_FRAMES, frameSize, pSles->fifo2Buffer);
568         //            } else {
569         //                fprintf(stderr, "sf_open failed\n");
570         //            }
571         //        } else {
572         //            sndfile = NULL;
573         //        }
574 
575         initBufferStats(&pSles->recorderBufferStats);
576         initBufferStats(&pSles->playerBufferStats);
577 
578         // init other variables needed for buffer test
579         pSles->testType = testType;
580         pSles->frequency1 = frequency1;
581         pSles->bufferTestPhase1 = 0;
582         pSles->count = 0;
583         pSles->byteBufferPtr = byteBufferPtr;
584         pSles->byteBufferLength = byteBufferLength;
585 
586         //init loopback tone
587         pSles->loopbackTone = loopbackTone;
588 
589         pSles->recorderTimeStamps = {
590             new int[maxRecordedLateCallbacks],      //int* timeStampsMs
591             new short[maxRecordedLateCallbacks],    //short* callbackDurations
592             0,                                      //short index
593             {0,0},                                  //struct timespec startTime;
594             maxRecordedLateCallbacks,               //int capacity
595             false                                   //bool exceededCapacity
596         };
597 
598         pSles->playerTimeStamps = {
599             new int[maxRecordedLateCallbacks],      //int* timeStampsMs
600             new short[maxRecordedLateCallbacks],    //short* callbackDurations;
601             0,                                      //short index
602             {0,0},                                  //struct timespec startTime;
603             maxRecordedLateCallbacks,               //int capacity
604             false                                   //bool exceededCapacity
605         };
606 
607         pSles->expectedBufferPeriod = (short) (
608                 round(pSles->bufSizeInFrames * MILLIS_PER_SECOND / (float) pSles->sampleRate));
609 
610         SLresult result;
611 
612         // create engine
613 #if 0
614         pSles->engineObject;
615 #endif
616         result = slCreateEngine(&(pSles->engineObject), 0, NULL, 0, NULL, NULL);
617         ASSERT_EQ(SL_RESULT_SUCCESS, result);
618         result = (*(pSles->engineObject))->Realize(pSles->engineObject, SL_BOOLEAN_FALSE);
619         ASSERT_EQ(SL_RESULT_SUCCESS, result);
620         SLEngineItf engineEngine;
621         result = (*(pSles->engineObject))->GetInterface(pSles->engineObject, SL_IID_ENGINE,
622                 &engineEngine);
623         ASSERT_EQ(SL_RESULT_SUCCESS, result);
624 
625         // create output mix
626 #if 0
627         pSles->outputmixObject;
628 #endif
629         result = (*engineEngine)->CreateOutputMix(engineEngine, &(pSles->outputmixObject), 0, NULL,
630                 NULL);
631         ASSERT_EQ(SL_RESULT_SUCCESS, result);
632         result = (*(pSles->outputmixObject))->Realize(pSles->outputmixObject, SL_BOOLEAN_FALSE);
633         ASSERT_EQ(SL_RESULT_SUCCESS, result);
634 
635         // create an audio player with buffer queue source and output mix sink
636         SLDataSource audiosrc;
637         SLDataSink audiosnk;
638         SLDataFormat_PCM pcm;
639         SLDataLocator_OutputMix locator_outputmix;
640         SLDataLocator_BufferQueue locator_bufferqueue_tx;
641         locator_bufferqueue_tx.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
642         locator_bufferqueue_tx.numBuffers = pSles->txBufCount;
643         locator_outputmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
644         locator_outputmix.outputMix = pSles->outputmixObject;
645         pcm.formatType = SL_DATAFORMAT_PCM;
646         pcm.numChannels = pSles->channels;
647         pcm.samplesPerSec = pSles->sampleRate * 1000;
648         pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
649         pcm.containerSize = 16;
650         pcm.channelMask = pSles->channels == 1 ? SL_SPEAKER_FRONT_CENTER :
651                 (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);
652         pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
653         audiosrc.pLocator = &locator_bufferqueue_tx;
654         audiosrc.pFormat = &pcm;
655         audiosnk.pLocator = &locator_outputmix;
656         audiosnk.pFormat = NULL;
657         pSles->playerObject = NULL;
658         pSles->recorderObject = NULL;
659         SLInterfaceID ids_tx[2] = {SL_IID_BUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION};
660         SLboolean flags_tx[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
661         result = (*engineEngine)->CreateAudioPlayer(engineEngine, &(pSles->playerObject),
662                 &audiosrc, &audiosnk, 2, ids_tx, flags_tx);
663         if (SL_RESULT_CONTENT_UNSUPPORTED == result) {
664             SLES_PRINTF("ERROR: Could not create audio player (result %x), check sample rate\n",
665                                                      result);
666             goto cleanup;
667         }
668         ASSERT_EQ(SL_RESULT_SUCCESS, result);
669 
670         {
671            /* Get the Android configuration interface which is explicit */
672             SLAndroidConfigurationItf configItf;
673             result = (*(pSles->playerObject))->GetInterface(pSles->playerObject,
674                                                  SL_IID_ANDROIDCONFIGURATION, (void*)&configItf);
675             ASSERT_EQ(SL_RESULT_SUCCESS, result);
676 
677             /* Use the configuration interface to configure the player before it's realized */
678             if (performanceMode != -1) {
679                 SLuint32 performanceMode32 = performanceMode;
680                 result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE,
681                         &performanceMode32, sizeof(SLuint32));
682                 ASSERT_EQ(SL_RESULT_SUCCESS, result);
683             }
684 
685         }
686 
687         result = (*(pSles->playerObject))->Realize(pSles->playerObject, SL_BOOLEAN_FALSE);
688         ASSERT_EQ(SL_RESULT_SUCCESS, result);
689         SLPlayItf playerPlay;
690         result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, SL_IID_PLAY,
691                 &playerPlay);
692         ASSERT_EQ(SL_RESULT_SUCCESS, result);
693         result = (*(pSles->playerObject))->GetInterface(pSles->playerObject, SL_IID_BUFFERQUEUE,
694                 &(pSles->playerBufferQueue));
695         ASSERT_EQ(SL_RESULT_SUCCESS, result);
696         result = (*(pSles->playerBufferQueue))->RegisterCallback(pSles->playerBufferQueue,
697                 playerCallback, pSles); //playerCallback is the name of callback function
698         ASSERT_EQ(SL_RESULT_SUCCESS, result);
699 
700         // Enqueue some zero buffers for the player
701         for (j = 0; j < pSles->txBufCount; ++j) {
702 
703             // allocate a free buffer
704             ASSERT(pSles->freeFront != pSles->freeRear);
705             char *buffer = pSles->freeBuffers[pSles->freeFront];
706             if (++pSles->freeFront > pSles->freeBufCount) {
707                 pSles->freeFront = 0;
708             }
709 
710             // put on play queue
711             SLuint32 txRearNext = pSles->txRear + 1;
712             if (txRearNext > pSles->txBufCount) {
713                 txRearNext = 0;
714             }
715             ASSERT(txRearNext != pSles->txFront);
716             pSles->txBuffers[pSles->txRear] = buffer;
717             pSles->txRear = txRearNext;
718             result = (*(pSles->playerBufferQueue))->Enqueue(pSles->playerBufferQueue,
719                     buffer, pSles->bufSizeInBytes);
720             ASSERT_EQ(SL_RESULT_SUCCESS, result);
721         }
722 
723         result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
724         ASSERT_EQ(SL_RESULT_SUCCESS, result);
725 
726         // Create an audio recorder with microphone device source and buffer queue sink.
727         // The buffer queue as sink is an Android-specific extension.
728         SLDataLocator_IODevice locator_iodevice;
729         SLDataLocator_AndroidSimpleBufferQueue locator_bufferqueue_rx;
730 
731         locator_iodevice.locatorType = SL_DATALOCATOR_IODEVICE;
732         locator_iodevice.deviceType = SL_IODEVICE_AUDIOINPUT;
733         locator_iodevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
734         locator_iodevice.device = NULL;
735 
736         audiosrc.pLocator = &locator_iodevice;
737         audiosrc.pFormat = NULL;
738 
739         locator_bufferqueue_rx.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
740         locator_bufferqueue_rx.numBuffers = pSles->rxBufCount;
741 
742         audiosnk.pLocator = &locator_bufferqueue_rx;
743         audiosnk.pFormat = &pcm;
744 
745         {   //why brackets here?
746             SLInterfaceID ids_rx[2] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
747                                        SL_IID_ANDROIDCONFIGURATION};
748             SLboolean flags_rx[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
749             result = (*engineEngine)->CreateAudioRecorder(engineEngine, &(pSles->recorderObject),
750                     &audiosrc, &audiosnk, 2, ids_rx, flags_rx);
751             if (SL_RESULT_SUCCESS != result) {
752                 status = STATUS_FAIL;
753 
754                 SLES_PRINTF("ERROR: Could not create audio recorder (result %x), "
755                              "check sample rate and channel count\n", result);
756                 goto cleanup;
757             }
758         }
759         ASSERT_EQ(SL_RESULT_SUCCESS, result);
760 
761         {
762            /* Get the Android configuration interface which is explicit */
763             SLAndroidConfigurationItf configItf;
764             result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject,
765                                                  SL_IID_ANDROIDCONFIGURATION, (void*)&configItf);
766             ASSERT_EQ(SL_RESULT_SUCCESS, result);
767 
768             SLuint32 presetValue = micSource;
769             //SL_ANDROID_RECORDING_PRESET_CAMCORDER;//SL_ANDROID_RECORDING_PRESET_NONE;
770 
771             /* Use the configuration interface to configure the recorder before it's realized */
772             if (presetValue != SL_ANDROID_RECORDING_PRESET_NONE) {
773                 result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_RECORDING_PRESET,
774                         &presetValue, sizeof(SLuint32));
775                 ASSERT_EQ(SL_RESULT_SUCCESS, result);
776             }
777             if (performanceMode != -1) {
778                 SLuint32 performanceMode32 = performanceMode;
779                 result = (*configItf)->SetConfiguration(configItf, SL_ANDROID_KEY_PERFORMANCE_MODE,
780                         &performanceMode32, sizeof(SLuint32));
781                 ASSERT_EQ(SL_RESULT_SUCCESS, result);
782             }
783 
784         }
785 
786         result = (*(pSles->recorderObject))->Realize(pSles->recorderObject, SL_BOOLEAN_FALSE);
787         ASSERT_EQ(SL_RESULT_SUCCESS, result);
788 
789         SLRecordItf recorderRecord;
790         result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject, SL_IID_RECORD,
791                 &recorderRecord);
792         ASSERT_EQ(SL_RESULT_SUCCESS, result);
793 
794         result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject,
795                 SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &(pSles->recorderBufferQueue));
796         ASSERT_EQ(SL_RESULT_SUCCESS, result);
797 
798         result = (*(pSles->recorderBufferQueue))->RegisterCallback(pSles->recorderBufferQueue,
799                 recorderCallback, pSles);
800         ASSERT_EQ(SL_RESULT_SUCCESS, result);
801 
802         // Enqueue some empty buffers for the recorder
803         for (j = 0; j < pSles->rxBufCount; ++j) {
804 
805             // allocate a free buffer
806             ASSERT(pSles->freeFront != pSles->freeRear);
807             char *buffer = pSles->freeBuffers[pSles->freeFront];
808             if (++pSles->freeFront > pSles->freeBufCount) {
809                 pSles->freeFront = 0;
810             }
811 
812             // put on record queue
813             SLuint32 rxRearNext = pSles->rxRear + 1;
814             if (rxRearNext > pSles->rxBufCount) {
815                 rxRearNext = 0;
816             }
817             ASSERT(rxRearNext != pSles->rxFront);
818             pSles->rxBuffers[pSles->rxRear] = buffer;
819             pSles->rxRear = rxRearNext;
820             result = (*(pSles->recorderBufferQueue))->Enqueue(pSles->recorderBufferQueue,
821                     buffer, pSles->bufSizeInBytes);
822             ASSERT_EQ(SL_RESULT_SUCCESS, result);
823         }
824 
825         // Kick off the recorder
826         result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING);
827         ASSERT_EQ(SL_RESULT_SUCCESS, result);
828 
829 
830 
831         // Tear down the objects and exit
832         status = STATUS_SUCCESS;
833         cleanup:
834 
835         SLES_PRINTF("Finished initialization with status: %d", status);
836 
837     }
838     return status;
839 }
840 
841 // Read data from fifo2Buffer and store into pSamples.
slesProcessNext(void * pCtx,double * pSamples,long maxSamples)842 int slesProcessNext(void *pCtx, double *pSamples, long maxSamples) {
843     //int status = STATUS_FAIL;
844     sles_data *pSles = (sles_data*)pCtx;
845 
846     SLES_PRINTF("slesProcessNext: pSles = %p, currentSample: %p,  maxSamples = %ld",
847                 pSles, pSamples, maxSamples);
848 
849     int samplesRead = 0;
850 
851     int currentSample = 0;
852     double *pCurrentSample = pSamples;
853     int maxValue = 32768;
854 
855     if (pSles != NULL) {
856 
857         SLresult result;
858         for (int i = 0; i < 10; i++) {
859             usleep(100000);         // sleep for 0.1s
860             if (pSles->fifo2Buffer != NULL) {
861                 for (;;) {
862                     short buffer[pSles->bufSizeInFrames * pSles->channels];
863                     ssize_t actual = audio_utils_fifo_read(&(pSles->fifo2), buffer,
864                             pSles->bufSizeInFrames);
865                     if (actual <= 0)
866                         break;
867                     {
868                         for (int jj = 0; jj < actual && currentSample < maxSamples; jj++) {
869                             *(pCurrentSample++) = ((double) buffer[jj]) / maxValue;
870                             currentSample++;
871                         }
872                     }
873                     samplesRead += actual;
874                 }
875             }
876             if (pSles->injectImpulse > 0) {
877                 if (pSles->injectImpulse <= 100) {
878                     pSles->injectImpulse = -1;
879                     write(1, "I", 1);
880                 } else {
881                     if ((pSles->injectImpulse % 1000) < 100) {
882                         write(1, "i", 1);
883                     }
884                     pSles->injectImpulse -= 100;
885                 }
886             } else if (i == 9) {
887                 write(1, ".", 1);
888             }
889         }
890         SLBufferQueueState playerBQState;
891         result = (*(pSles->playerBufferQueue))->GetState(pSles->playerBufferQueue,
892                   &playerBQState);
893         ASSERT_EQ(SL_RESULT_SUCCESS, result);
894         SLAndroidSimpleBufferQueueState recorderBQState;
895         result = (*(pSles->recorderBufferQueue))->GetState(pSles->recorderBufferQueue,
896                   &recorderBQState);
897         ASSERT_EQ(SL_RESULT_SUCCESS, result);
898 
899         SLES_PRINTF("End of slesProcessNext: pSles = %p, samplesRead = %d, maxSamples = %ld",
900                     pSles, samplesRead, maxSamples);
901     }
902     return samplesRead;
903 }
904 
905 
slesDestroyServer(sles_data * pSles)906 static int slesDestroyServer(sles_data *pSles) {
907     int status = STATUS_FAIL;
908 
909      SLES_PRINTF("Start slesDestroyServer: pSles = %p", pSles);
910 
911     if (pSles != NULL) {
912         if (NULL != pSles->playerObject) {
913             SLES_PRINTF("stopping player...");
914             SLPlayItf playerPlay;
915             SLresult result = (*(pSles->playerObject))->GetInterface(pSles->playerObject,
916                                                         SL_IID_PLAY, &playerPlay);
917 
918             ASSERT_EQ(SL_RESULT_SUCCESS, result);
919 
920             //stop player and recorder if they exist
921              result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_STOPPED);
922             ASSERT_EQ(SL_RESULT_SUCCESS, result);
923         }
924 
925         if (NULL != pSles->recorderObject) {
926             SLES_PRINTF("stopping recorder...");
927             SLRecordItf recorderRecord;
928             SLresult result = (*(pSles->recorderObject))->GetInterface(pSles->recorderObject,
929                                                           SL_IID_RECORD, &recorderRecord);
930             ASSERT_EQ(SL_RESULT_SUCCESS, result);
931 
932             result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED);
933             ASSERT_EQ(SL_RESULT_SUCCESS, result);
934         }
935 
936         usleep(1000);
937 
938         audio_utils_fifo_deinit(&(pSles->fifo));
939         delete[] pSles->fifoBuffer;
940 
941         SLES_PRINTF("slesDestroyServer 2");
942 
943         //        if (sndfile != NULL) {
944         audio_utils_fifo_deinit(&(pSles->fifo2));
945         delete[] pSles->fifo2Buffer;
946 
947         SLES_PRINTF("slesDestroyServer 3");
948 
949         //            sf_close(sndfile);
950         //        }
951         if (NULL != pSles->playerObject) {
952             (*(pSles->playerObject))->Destroy(pSles->playerObject);
953         }
954 
955         SLES_PRINTF("slesDestroyServer 4");
956 
957         if (NULL != pSles->recorderObject) {
958             (*(pSles->recorderObject))->Destroy(pSles->recorderObject);
959         }
960 
961         SLES_PRINTF("slesDestroyServer 5");
962 
963         (*(pSles->outputmixObject))->Destroy(pSles->outputmixObject);
964         SLES_PRINTF("slesDestroyServer 6");
965         (*(pSles->engineObject))->Destroy(pSles->engineObject);
966         SLES_PRINTF("slesDestroyServer 7");
967 
968         //free buffers
969         if (NULL != pSles->freeBuffers) {
970             for (unsigned j = 0; j < pSles->freeBufCount; ++j) {
971                 if (NULL != pSles->freeBuffers[j]) {
972                     SLES_PRINTF(" free buff%d at %p",j, pSles->freeBuffers[j]);
973                     free (pSles->freeBuffers[j]);
974                 }
975             }
976             SLES_PRINTF("  free freeBuffers at %p", pSles->freeBuffers);
977             free(pSles->freeBuffers);
978         } else {
979             SLES_PRINTF("  freeBuffers NULL, no need to free");
980         }
981 
982 
983         if (NULL != pSles->rxBuffers) {
984             SLES_PRINTF("  free rxBuffers at %p", pSles->rxBuffers);
985             free(pSles->rxBuffers);
986         } else {
987             SLES_PRINTF("  rxBuffers NULL, no need to free");
988         }
989 
990         if (NULL != pSles->txBuffers) {
991             SLES_PRINTF("  free txBuffers at %p", pSles->txBuffers);
992             free(pSles->txBuffers);
993         } else {
994             SLES_PRINTF("  txBuffers NULL, no need to free");
995         }
996 
997 
998         status = STATUS_SUCCESS;
999     }
1000     SLES_PRINTF("End slesDestroyServer: status = %d", status);
1001     return status;
1002 }
1003 
1004 
slesGetRecorderBufferPeriod(void * pCtx)1005 int* slesGetRecorderBufferPeriod(void *pCtx) {
1006     sles_data *pSles = (sles_data*)pCtx;
1007     return pSles->recorderBufferStats.buffer_period;
1008 }
1009 
slesGetRecorderMaxBufferPeriod(void * pCtx)1010 int slesGetRecorderMaxBufferPeriod(void *pCtx) {
1011     sles_data *pSles = (sles_data*)pCtx;
1012     return pSles->recorderBufferStats.max_buffer_period;
1013 }
1014 
slesGetRecorderVarianceBufferPeriod(void * pCtx)1015 int64_t slesGetRecorderVarianceBufferPeriod(void *pCtx) {
1016     sles_data *pSles = (sles_data*)pCtx;
1017     return pSles->recorderBufferStats.var;
1018 }
1019 
slesGetPlayerBufferPeriod(void * pCtx)1020 int* slesGetPlayerBufferPeriod(void *pCtx) {
1021     sles_data *pSles = (sles_data*)pCtx;
1022     return pSles->playerBufferStats.buffer_period;
1023 }
1024 
slesGetPlayerMaxBufferPeriod(void * pCtx)1025 int slesGetPlayerMaxBufferPeriod(void *pCtx) {
1026     sles_data *pSles = (sles_data*)pCtx;
1027     return pSles->playerBufferStats.max_buffer_period;
1028 }
1029 
slesGetPlayerVarianceBufferPeriod(void * pCtx)1030 int64_t slesGetPlayerVarianceBufferPeriod(void *pCtx) {
1031     sles_data *pSles = (sles_data*)pCtx;
1032     return pSles->playerBufferStats.var;
1033 }
1034 
slesGetCaptureRank(void * pCtx)1035 int slesGetCaptureRank(void *pCtx) {
1036     sles_data *pSles = (sles_data*)pCtx;
1037     // clear the capture flags since they're being handled now
1038     int recorderRank = android_atomic_exchange(0, &pSles->recorderBufferStats.captureRank);
1039     int playerRank = android_atomic_exchange(0, &pSles->playerBufferStats.captureRank);
1040 
1041     if (recorderRank > playerRank) {
1042         return recorderRank;
1043     } else {
1044         return playerRank;
1045     }
1046 }
1047 
slesGetPlayerTimeStampsAndExpectedBufferPeriod(void * pCtx,callbackTimeStamps ** ppTSs)1048 int slesGetPlayerTimeStampsAndExpectedBufferPeriod(void *pCtx, callbackTimeStamps **ppTSs) {
1049     sles_data *pSles = (sles_data*)pCtx;
1050     *ppTSs = &pSles->playerTimeStamps;
1051     return pSles->expectedBufferPeriod;
1052 }
1053 
slesGetRecorderTimeStampsAndExpectedBufferPeriod(void * pCtx,callbackTimeStamps ** ppTSs)1054 int slesGetRecorderTimeStampsAndExpectedBufferPeriod(void *pCtx, callbackTimeStamps **ppTSs) {
1055     sles_data *pSles = (sles_data*)pCtx;
1056     *ppTSs = &pSles->recorderTimeStamps;
1057     return pSles->expectedBufferPeriod;
1058 }
1059