Bug 1104643 - Interpolate the audio clock by system clock if the qudio clock is not going forward. r=padenot
authorBenjamin Chen <bechen@mozilla.com>
Tue, 05 May 2015 16:00:14 +0800
changeset 243340 7a7035e9ebfc9adcb6dc23de77bc251d2cb1b1bf
parent 243339 88c3789d70cb83d0c582d17bca151b808089ed26
child 243341 39c35b0c2e04ccdbf8c91e9e35d84218c4c98c0b
push id28738
push usercbook@mozilla.com
push dateTue, 12 May 2015 14:11:31 +0000
treeherdermozilla-central@bedce1b405a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1104643
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1104643 - Interpolate the audio clock by system clock if the qudio clock is not going forward. r=padenot
media/libcubeb/src/cubeb_opensl.c
--- a/media/libcubeb/src/cubeb_opensl.c
+++ b/media/libcubeb/src/cubeb_opensl.c
@@ -6,16 +6,17 @@
  */
 #undef NDEBUG
 #include <assert.h>
 #include <dlfcn.h>
 #include <stdlib.h>
 #include <pthread.h>
 #include <SLES/OpenSLES.h>
 #include <math.h>
+#include <time.h>
 #if defined(__ANDROID__)
 #include <sys/system_properties.h>
 #include "android/sles_definitions.h"
 #include <SLES/OpenSLES_Android.h>
 #include <android/log.h>
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Cubeb_OpenSL" , ## args)
 #define ANDROID_VERSION_GINGERBREAD_MR1 10
 #endif
@@ -65,16 +66,19 @@ struct cubeb_stream {
   cubeb_data_callback data_callback;
   cubeb_state_callback state_callback;
   void * user_ptr;
 
   cubeb_resampler * resampler;
   unsigned int inputrate;
   unsigned int outputrate;
   unsigned int latency;
+  int64_t lastPosition;
+  int64_t lastPositionTimeStamp;
+  int64_t lastCompensativePosition;
 };
 
 static void
 play_callback(SLPlayItf caller, void * user_ptr, SLuint32 event)
 {
   cubeb_stream * stm = user_ptr;
   int draining;
   assert(stm);
@@ -506,16 +510,19 @@ opensl_stream_init(cubeb * ctx, cubeb_st
   stm->data_callback = data_callback;
   stm->state_callback = state_callback;
   stm->user_ptr = user_ptr;
 
   stm->inputrate = stream_params.rate;
   stm->latency = latency;
   stm->stream_type = stream_params.stream_type;
   stm->framesize = stream_params.channels * sizeof(int16_t);
+  stm->lastPosition = -1;
+  stm->lastPositionTimeStamp = 0;
+  stm->lastCompensativePosition = -1;
 
   int r = pthread_mutex_init(&stm->mutex, NULL);
   assert(r == 0);
 
   SLDataLocator_BufferQueue loc_bufq;
   loc_bufq.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
   loc_bufq.numBuffers = NBUFS;
   SLDataSource source;
@@ -692,40 +699,53 @@ opensl_stream_stop(cubeb_stream * stm)
 static int
 opensl_stream_get_position(cubeb_stream * stm, uint64_t * position)
 {
   SLmillisecond msec;
   uint64_t samplerate;
   SLresult res;
   int r;
   uint32_t mixer_latency;
+  uint32_t compensation_msec = 0;
 
   res = (*stm->play)->GetPosition(stm->play, &msec);
   if (res != SL_RESULT_SUCCESS)
     return CUBEB_ERROR;
 
+  struct timespec t;
+  clock_gettime(CLOCK_MONOTONIC, &t);
+  if(stm->lastPosition == msec || msec < stm->lastCompensativePosition) {
+    compensation_msec =
+      (t.tv_sec*1000000000LL + t.tv_nsec - stm->lastPositionTimeStamp) / 1000000;
+  } else {
+    stm->lastPositionTimeStamp = t.tv_sec*1000000000LL + t.tv_nsec;
+    stm->lastPosition = msec;
+  }
+
   samplerate = stm->inputrate;
 
   r = stm->context->get_output_latency(&mixer_latency, stm->stream_type);
   if (r) {
     return CUBEB_ERROR;
   }
 
   pthread_mutex_lock(&stm->mutex);
   int64_t maximum_position = stm->written * (int64_t)stm->inputrate / stm->outputrate;
   pthread_mutex_unlock(&stm->mutex);
   assert(maximum_position >= 0);
 
   if (msec > mixer_latency) {
-    int64_t unadjusted_position = samplerate * (msec - mixer_latency) / 1000;
+    int64_t unadjusted_position =
+      samplerate * (msec - mixer_latency + compensation_msec) / 1000;
     *position = unadjusted_position < maximum_position ?
       unadjusted_position : maximum_position;
   } else {
     *position = 0;
   }
+  stm->lastCompensativePosition = *position;
   return CUBEB_OK;
 }
 
 int
 opensl_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
 {
   int r;
   uint32_t mixer_latency; // The latency returned by AudioFlinger is in ms.