diff --git a/headers/os/media/TimedEventQueue.h b/headers/os/media/TimedEventQueue.h index 732fd1727b..ce00b5b6ed 100644 --- a/headers/os/media/TimedEventQueue.h +++ b/headers/os/media/TimedEventQueue.h @@ -38,8 +38,9 @@ struct media_timed_event { int32 data; int64 bigdata; char user_data[64]; + bigtime_t enqueue_time; - uint32 _reserved_media_timed_event_[8]; + uint32 _reserved_media_timed_event_[6]; }; diff --git a/src/kits/media/MediaEventLooper.cpp b/src/kits/media/MediaEventLooper.cpp index 85af33acc6..3eae84481a 100644 --- a/src/kits/media/MediaEventLooper.cpp +++ b/src/kits/media/MediaEventLooper.cpp @@ -242,11 +242,24 @@ BMediaEventLooper::ControlLoop() err = fRealTimeQueue.RemoveFirstEvent(&event); if (err == B_OK) { - // We are going to do this calculus in real time - // because otherwise we could get erroneous values. - // This calculus allow us to detect both early and late - // buffers, this is the meaning of the lateness concept. - bigtime_t lateness = waitUntil - TimeSource()->RealTime(); + // The general idea of lateness is to allow + // the client code to detect when the buffer + // is handled late or early. What we add is + // that the code log the time at which the + // current event is added to the queue. This + // allow us to detect cyclic/stagnant latency + // in the meantime, so that the client can + // notify to the producer only the portion + // that might be attributable. + bigtime_t lateness = 0; + if (waitUntil > 0) { + lateness = waitUntil - TimeSource()->RealTime(); + if (lateness > 0) { + bigtime_t enqueueLatency = event.enqueue_time - waitUntil; + if (enqueueLatency > 0) + lateness += enqueueLatency; + } + } DispatchEvent(&event, -lateness, hasRealtime); } } else if (err != B_OK) diff --git a/src/kits/media/TimedEventQueuePrivate.cpp b/src/kits/media/TimedEventQueuePrivate.cpp index 6b5be4d988..4e39b83f50 100644 --- a/src/kits/media/TimedEventQueuePrivate.cpp +++ b/src/kits/media/TimedEventQueuePrivate.cpp @@ -78,6 +78,9 @@ _event_queue_imp::AddEvent(const media_timed_event &event) return B_BAD_VALUE; } + const_cast(event).enqueue_time = + BTimeSource::RealTime(); + //create a new queue if (fFirstEntry == NULL) { ASSERT(fEventCount == 0);