Bug 1375411 - notify drained if we didn't write any sample. draft
authorAlastor Wu <alwu@mozilla.com>
Wed, 12 Jul 2017 17:05:46 +0800
changeset 607490 c45d79ec35fe9656484fe7f59f19c6edc015913c
parent 603204 6f8f10f48ace5692256efd91f011bd23054ee2ec
child 637033 8fc605ebfe1f730a974ceb7185c49827d12cf281
push id67990
push useralwu@mozilla.com
push dateWed, 12 Jul 2017 09:06:03 +0000
bugs1375411
milestone56.0a1
Bug 1375411 - notify drained if we didn't write any sample. The time stretching would fail on very short audio file. Since the input/output of time-stretcher is not a linear function, it only returns result if we feed it enough samples. When the resample returns zero sample in this situation, cubeb should call drained initiative. MozReview-Commit-ID: 6uK0kyKU5tq
media/libcubeb/src/cubeb_opensl.c
--- a/media/libcubeb/src/cubeb_opensl.c
+++ b/media/libcubeb/src/cubeb_opensl.c
@@ -182,16 +182,39 @@ opensl_set_draining(cubeb_stream * stm, 
   int r = pthread_mutex_trylock(&stm->mutex);
   LOG("set draining try r = %d", r);
   assert((r == EDEADLK || r == EBUSY) && "set_draining: mutex should be locked but it's not.");
 #endif
   assert(value == 0 || value == 1);
   stm->draining = value;
 }
 
+static void
+opensl_notify_drained(cubeb_stream * stm)
+{
+  assert(stm);
+  int r = pthread_mutex_lock(&stm->mutex);
+  assert(r == 0);
+  int draining = opensl_get_draining(stm);
+  r = pthread_mutex_unlock(&stm->mutex);
+  assert(r == 0);
+  if (draining) {
+    stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
+    if (stm->play) {
+      LOG("stop player in play_callback");
+      r = opensl_stop_player(stm);
+      assert(r == CUBEB_OK);
+    }
+    if (stm->recorderItf) {
+      r = opensl_stop_recorder(stm);
+      assert(r == CUBEB_OK);
+    }
+  }
+}
+
 static uint32_t
 opensl_get_shutdown(cubeb_stream * stm)
 {
 #ifdef DEBUG
   int r = pthread_mutex_trylock(&stm->mutex);
   assert((r == EDEADLK || r == EBUSY) && "get_shutdown: mutex should be locked but it's not.");
 #endif
   return stm->shutdown;
@@ -212,34 +235,17 @@ opensl_set_shutdown(cubeb_stream * stm, 
 static void
 play_callback(SLPlayItf caller, void * user_ptr, SLuint32 event)
 {
   cubeb_stream * stm = user_ptr;
   int draining;
   assert(stm);
   switch (event) {
     case SL_PLAYEVENT_HEADATMARKER:
-    {
-      int r = pthread_mutex_lock(&stm->mutex);
-      assert(r == 0);
-      draining = opensl_get_draining(stm);
-      r = pthread_mutex_unlock(&stm->mutex);
-      assert(r == 0);
-      if (draining) {
-        stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
-        if (stm->play) {
-          r = opensl_stop_player(stm);
-          assert(r == CUBEB_OK);
-        }
-        if (stm->recorderItf) {
-          r = opensl_stop_recorder(stm);
-          assert(r == CUBEB_OK);
-        }
-      }
-    }
+      opensl_notify_drained(stm);
     break;
   default:
     break;
   }
 }
 
 static void
 recorder_marker_callback (SLRecordItf caller, void * pContext, SLuint32 event)
@@ -325,19 +331,26 @@ bufferqueue_callback(SLBufferQueueItf ca
   if (!draining && written * stm->framesize < stm->queuebuf_len) {
     LOG("bufferqueue_callback draining");
     r = pthread_mutex_lock(&stm->mutex);
     assert(r == 0);
     int64_t written_duration = INT64_C(1000) * stm->written * stm->framesize / stm->bytespersec;
     opensl_set_draining(stm, 1);
     r = pthread_mutex_unlock(&stm->mutex);
     assert(r == 0);
-    // Use SL_PLAYEVENT_HEADATMARKER event from slPlayCallback of SLPlayItf
-    // to make sure all the data has been processed.
-    (*stm->play)->SetMarkerPosition(stm->play, (SLmillisecond)written_duration);
+
+    if (written_duration == 0) {
+      // since we didn't write any sample, it's not possible to reach the marker
+      // time and trigger the callback. We should initiative notify drained.
+      opensl_notify_drained(stm);
+    } else {
+      // Use SL_PLAYEVENT_HEADATMARKER event from slPlayCallback of SLPlayItf
+      // to make sure all the data has been processed.
+      (*stm->play)->SetMarkerPosition(stm->play, (SLmillisecond)written_duration);
+    }
     return;
   }
 }
 
 static int
 opensl_enqueue_recorder(cubeb_stream * stm, void ** last_filled_buffer)
 {
   assert(stm);