mLateWindow = TIME_UNIT.convert(lateWindow, unit);
mStreamIndex = streamIndex;
// create and start the thread
Thread t = new Thread(name)
{
public void run()
{
try
{
log.debug("thread started");
boolean isDone = false;
DelayedItem<IMediaData> delayedItem = null;
// wait for all the other stream threads to wakeup
synchronized (SelfServicingMediaQueue.this)
{
mIsInitialized = true;
SelfServicingMediaQueue.this.notifyAll();
}
// start processing media
while (!isDone)
{
// synchronized (SelfServicingMediaQueue.this)
mLock.lock();
try
{
// while not done, and no item, wait for one
while (!mDone && (delayedItem = mQueue.poll()) == null)
{
try
{
mCondition.await();
}
catch (InterruptedException e)
{
// interrupt and return
Thread.currentThread().interrupt();
return;
}
}
// notify the queue that data extracted
mCondition.signalAll();
// record "atomic" done
isDone = mDone;
}
finally
{
mLock.unlock();
}
// if there is an item, dispatch it
if (null != delayedItem)
{
IMediaData item = delayedItem.getItem();
try
{
do
{
// this is the story of goldilocks testing the the media
long now = getMediaTime();
long delta = delayedItem.getTimeStamp() - now;
// if the media is too new and unripe, goldilocks sleeps
// for a bit
if (delta >= mEarlyWindow)
{
//debug("delta: " + delta);
try
{
//sleep(MILLISECONDS.convert(delta - mEarlyWindow, TIME_UNIT));
sleep(MILLISECONDS.convert(delta / 3, TIME_UNIT));
}
catch (InterruptedException e)
{
// interrupt and return
Thread.currentThread().interrupt();
return;
}
}
else
{
// if the media is old and moldy, goldilocks says
// "ick" and drops the media on the floor
if (delta < -mLateWindow)
{
debug(
"@%5d DROP queue[%2d]: %s[%5d] delta: %d",
MILLISECONDS.convert(now, TIME_UNIT),
mQueue.size(),
(item instanceof IVideoPicture ? "IMAGE"
: "sound"), MILLISECONDS.convert(delayedItem
.getTimeStamp(), TIME_UNIT), MILLISECONDS.convert(
delta, TIME_UNIT));
}
// if the media is just right, goldilocks dispaches it
// for presentiation becuse she's a badass bitch
else
{
dispatch(item, delayedItem.getTimeStamp());
// debug("%5d show [%2d]: %s[%5d] delta: %d",
// MILLISECONDS.convert(getPresentationTime(), TIME_UNIT),
// size(),
// (delayedItem.getItem() instanceof BufferedImage
// ? "IMAGE"
// : "sound"),
// MILLISECONDS.convert(delayedItem.getTimeStamp(),
// TIME_UNIT),
// MILLISECONDS.convert(delta, TIME_UNIT));
}
// and the moral of the story is don't mess with goldilocks
break;
}
}
while (!mDone);
}
finally
{
if (item != null)
item.delete();
}
}
}
}
finally
{
// close stats frame
if (null != mStatsFrame)
{
mStatsFrame.dispose();
mStatsFrame = null;
}
// close frame for this queue
MediaFrame frame = mFrames.get(mStreamIndex);
if (null != frame)
frame.dispose();
}
}
};
t.setPriority(priority);
t.setDaemon(true);
synchronized (this)
{
t.start();
try
{
while (!mIsInitialized)
this.wait();
}