diff --git a/headers/os/media/TimedEventQueue.h b/headers/os/media/TimedEventQueue.h index 190a792b1b..732fd1727b 100644 --- a/headers/os/media/TimedEventQueue.h +++ b/headers/os/media/TimedEventQueue.h @@ -38,9 +38,8 @@ struct media_timed_event { int32 data; int64 bigdata; char user_data[64]; - bigtime_t queued_time; // Real time when put in queue - uint32 _reserved_media_timed_event_[6]; + uint32 _reserved_media_timed_event_[8]; }; diff --git a/src/kits/media/MediaEventLooper.cpp b/src/kits/media/MediaEventLooper.cpp index 0ce44f56f8..d072bc3efb 100644 --- a/src/kits/media/MediaEventLooper.cpp +++ b/src/kits/media/MediaEventLooper.cpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2015 Dario Casalinuovo * Copyright (c) 2002, 2003 Marcus Overhagen * * Permission is hereby granted, free of charge, to any person obtaining @@ -212,68 +213,71 @@ BMediaEventLooper::ControlLoop() { CALLED(); - bool is_realtime = false; status_t err; - bigtime_t latency; - bigtime_t waituntil; - bigtime_t lateness; - for (;;) { - // while there are no events or it is not time for the earliest event, - // process messages using WaitForMessages. Whenever this funtion times out, - // we need to handle the next event - for (;;) { - if (RunState() == B_QUITTING) - return; - // BMediaEventLooper compensates your performance time by adding the event latency - // (see SetEventLatency()) and the scheduling latency (or, for real-time events, - // only the scheduling latency). + bigtime_t waitUntil = 0; + bigtime_t lateness = 0; + bool hasRealtime = false; + bool hasEvent = false; - latency = fEventLatency + fSchedulingLatency; - waituntil = B_INFINITE_TIMEOUT; - if (fEventQueue.HasEvents()) { - const media_timed_event *firstEvent = fEventQueue.FirstEvent(); - waituntil = TimeSource()->RealTimeFor(firstEvent->event_time, latency); - is_realtime = false; - lateness = firstEvent->queued_time - waituntil; - if (lateness > 0) { -// if (lateness > 1000) -// printf("node %02ld handling %12Ld at %12Ld -- %Ld late, queued at %Ld now %12Ld \n", -// ID(), fEventQueue.FirstEventTime(), TimeSource()->Now(), lateness, -// firstEvent->queued_time, TimeSource()->RealTime()); - is_realtime = false; - break; - } -// printf("node %02ld waiting for %12Ld that will happen at %12Ld\n", ID(), fEventQueue.FirstEventTime(), waituntil); - } - if (fRealTimeQueue.HasEvents()) { - const media_timed_event *firstEvent = fRealTimeQueue.FirstEvent(); - bigtime_t temp; - temp = firstEvent->event_time - fSchedulingLatency; - lateness = firstEvent->queued_time - temp; - if (lateness > 0) { - is_realtime = true; - break; - } - if (temp < waituntil) { - waituntil = temp; - is_realtime = true; - } - } - lateness = 0; // remove any extraneous value if we get this far - err = WaitForMessage(waituntil); - if (err == B_TIMED_OUT) - break; + // While there are no events or it is not time for the earliest event, + // process messages using WaitForMessages. Whenever this funtion times out, + // we need to handle the next event + + fSchedulingLatency = estimate_max_scheduling_latency(fControlThread); + while (true) { + if (RunState() == B_QUITTING) + return; + + // BMediaEventLooper compensates your performance time by adding + // the event latency (see SetEventLatency()) and the scheduling + // latency (or, for real-time events, only the scheduling latency). + + waitUntil = B_INFINITE_TIMEOUT; + hasRealtime = fRealTimeQueue.HasEvents(); + hasEvent = fEventQueue.HasEvents(); + + if (hasEvent) { + waitUntil = TimeSource()->RealTimeFor( + fEventQueue.FirstEvent()->event_time, + fEventLatency + fSchedulingLatency); + lateness = waitUntil; + } else if (!hasEvent && !hasRealtime) + goto ahead; + + if (hasEvent && hasRealtime) { + if (fRealTimeQueue.FirstEventTime() + - fSchedulingLatency <= waitUntil) { + hasEvent = false; + } else + hasRealtime = false; } - /// we have timed out - so handle the next event - media_timed_event event; - if (is_realtime) - err = fRealTimeQueue.RemoveFirstEvent(&event); - else - err = fEventQueue.RemoveFirstEvent(&event); -// printf("node %02ld handling %12Ld at %12Ld\n", ID(), event.event_time, TimeSource()->Now()); + if (hasRealtime) { + waitUntil = fRealTimeQueue.FirstEventTime() + - fSchedulingLatency; + lateness = waitUntil; + } - if (err == B_OK) DispatchEvent(&event, lateness, is_realtime); + if (waitUntil <= TimeSource()->RealTime()) + waitUntil = 0; + +ahead: + err = WaitForMessage(waitUntil); + if (err == B_TIMED_OUT) { + media_timed_event event; + if (hasEvent) + err = fEventQueue.RemoveFirstEvent(&event); + else + err = fRealTimeQueue.RemoveFirstEvent(&event); + + if (err == B_OK) { + lateness -= TimeSource()->RealTime(); + if (lateness < 0) + lateness = 0; + DispatchEvent(&event, lateness, hasRealtime); + } + } else if (err != B_OK) + return; } } diff --git a/src/kits/media/TimedEventQueuePrivate.cpp b/src/kits/media/TimedEventQueuePrivate.cpp index 3cc337c50a..6b5be4d988 100644 --- a/src/kits/media/TimedEventQueuePrivate.cpp +++ b/src/kits/media/TimedEventQueuePrivate.cpp @@ -78,8 +78,6 @@ _event_queue_imp::AddEvent(const media_timed_event &event) return B_BAD_VALUE; } - *(bigtime_t *)&event.queued_time = BTimeSource::RealTime(); - //create a new queue if (fFirstEntry == NULL) { ASSERT(fEventCount == 0);