diff options
Diffstat (limited to 'dxr3outputthread.c')
-rw-r--r-- | dxr3outputthread.c | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/dxr3outputthread.c b/dxr3outputthread.c new file mode 100644 index 0000000..5bfc7ac --- /dev/null +++ b/dxr3outputthread.c @@ -0,0 +1,239 @@ +/* + * dxr3outputthread.c + * + * Copyright (C) 2002-2004 Kai Möller + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <stdio.h> +#include <unistd.h> +#include <time.h> +#include "dxr3outputthread.h" + +// ================================== +const int AUDIO_OFFSET = 4500; +#define SCR m_dxr3Device.GetSysClock() +// ================================== + +// ================================== +//! constructor +cDxr3OutputThread::cDxr3OutputThread(cDxr3Interface& dxr3Device, + cDxr3SyncBuffer& buffer) : + cThread(), + m_dxr3Device(dxr3Device), + m_buffer(buffer), + m_bStopThread(false), + m_bNeedResync(false) +{ +} + +// ================================== +//! send stop signal +void cDxr3OutputThread::SetStopSignal() +{ + Lock(); + m_bStopThread = true; + Unlock(); +} + +// ================================== +//! was stop signal send? +bool cDxr3OutputThread::GetStopSignal() +{ + bool ret = false; + Lock(); + ret = m_bStopThread; + Unlock(); + + return ret; +} + +// ================================== +//! constr. +cDxr3AudioOutThread::cDxr3AudioOutThread(cDxr3Interface& dxr3Device, + cDxr3SyncBuffer& buffer) : + cDxr3OutputThread(dxr3Device, buffer) +{ + SetDescription("DXR3 audio output"); +} + +//! destructor +cDxr3AudioOutThread::~cDxr3AudioOutThread() +{ + m_buffer.Stop(); + SetStopSignal(); + Cancel(3); +} + +// ================================== +//! thread action +void cDxr3AudioOutThread::Action() +{ + bool resync = false; + uint32_t pts = 0; + + while (!GetStopSignal()) + { + pts = 0; + cFixedLengthFrame* pNext = m_buffer.Get(); + + if (pNext) pts = pNext->GetPts(); + + if (pts && abs((int)pts-(int)SCR) > 30000 || + m_dxr3Device.IsExternalReleased()) + { + m_buffer.Clear(); + m_bNeedResync = true; + } + else if (pNext) + { + if (!pts || pts < SCR) + { + if (!pts && resync) + { + continue; + } + else + { + resync = false; + } + + if (pts && (pts < SCR) && ((SCR - pts) > 5000)) + { + m_dxr3Device.SetSysClock(pts + 1 * AUDIO_OFFSET); + m_dxr3Device.PlayAudioFrame(pNext); + if (m_buffer.IsPolled()) + { + m_buffer.Clear(); + m_bNeedResync = true; + } + } + else + { + m_dxr3Device.PlayAudioFrame(pNext); + m_buffer.Pop(); + } + } + else + { + if (abs((int)pts - (int)SCR) < (AUDIO_OFFSET )) + { + m_dxr3Device.PlayAudioFrame(pNext); + m_buffer.Pop(); + } + } + } + + if ((pts > SCR && abs((int)pts - (int)SCR) > AUDIO_OFFSET)) + { + usleep(10000); + } + } +} + +// ================================== +//! constr. +cDxr3VideoOutThread::cDxr3VideoOutThread(cDxr3Interface& dxr3Device, + cDxr3SyncBuffer& buffer) : + cDxr3OutputThread(dxr3Device, buffer) +{ + SetDescription("DXR3 video output"); +} + +//! destructor +cDxr3VideoOutThread::~cDxr3VideoOutThread() +{ + m_buffer.Stop(); + SetStopSignal(); + Cancel(3); +} + +// ================================== +//! thread action +void cDxr3VideoOutThread::Action() +{ + uint32_t pts = 0; + static uint32_t lastPts = 0; + + while (!GetStopSignal()) + { + cFixedLengthFrame* pNext = m_buffer.Get(); + if (pNext) + { + pts = pNext->GetPts(); + if (pts == lastPts) + pts = 0; + + if (pts > SCR && abs((int)pts - (int)SCR) < 7500) + { + m_dxr3Device.SetPts(pts); + } + + if (!pts || pts < SCR) + { + if (m_buffer.Available()) + { + m_dxr3Device.PlayVideoFrame(pNext); + m_buffer.Pop(); + } + } + else + { + if ((pts > SCR) && abs((int)pts - (int)SCR) < 7500) + { + m_dxr3Device.SetPts(pts); + + if (m_buffer.Available() && pNext->GetData() && + pNext->GetCount()) + { + m_dxr3Device.PlayVideoFrame(pNext); + m_buffer.Pop(); + } + } + else + { + if (pts < SCR) + { + m_dxr3Device.PlayVideoFrame(pNext); + m_buffer.Pop(); + } + } + } + + + if (m_dxr3Device.IsExternalReleased()) + { + m_bNeedResync = true; + m_buffer.Clear(); + } + + if ((pts > SCR && abs((int)pts - (int)SCR) > 7500 )) + { + usleep(10000); + } + } + } +} + +#undef SCR + +// Local variables: +// mode: c++ +// c-file-style: "stroustrup" +// c-file-offsets: ((inline-open . 0)) +// indent-tabs-mode: t +// End: |