diff options
-rw-r--r-- | dxr3audiodecoder.c | 291 | ||||
-rw-r--r-- | dxr3syncbuffer.c | 216 |
2 files changed, 228 insertions, 279 deletions
diff --git a/dxr3audiodecoder.c b/dxr3audiodecoder.c index d670d19..a9dda79 100644 --- a/dxr3audiodecoder.c +++ b/dxr3audiodecoder.c @@ -2,7 +2,7 @@ * dxr3audiodecoder.c * * Copyright (C) 2002-2004 Kai Möller - * Copyright (C) 2004 Christian Gmeiner + * Copyright (C) 2004-2009 Christian Gmeiner * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -70,14 +70,14 @@ cDxr3AudioDecoder::cDxr3AudioDecoder() : rbuf(50000), ac3dtsDecoder(&rbuf) cDxr3AudioDecoder::~cDxr3AudioDecoder() { // close codec, if it is open - avcodec_close(contextAudio); + avcodec_close(contextAudio); } // ================================== //! (re)init ffmpeg codec void cDxr3AudioDecoder::Init() { - avcodec_close(contextAudio); + avcodec_close(contextAudio); // create a new codec context contextAudio = avcodec_alloc_context(); @@ -89,7 +89,7 @@ void cDxr3AudioDecoder::Init() } foundHeader = false; - decodeAudio = true; + decodeAudio = true; //lastHeader[0] = 0xFF; //lastHeader[1] = lastHeader[2] = lastHeader[3] = 0; @@ -104,92 +104,79 @@ void cDxr3AudioDecoder::Decode(cDxr3PesFrame *frame, uint32_t pts, cDxr3SyncBuff enum audioException { - WRONG_LENGTH, + WRONG_LENGTH, }; const uint8_t *buf = frame->GetPayload(); int length = frame->GetPayloadLength(); int i = 0; - for (i = 0; i < length-4 && !foundHeader; i++) - { - unsigned int tempHead = *((unsigned int*)(buf+i)); - if (HeadCheck(tempHead)) - { - if ((buf[i+2] & 0xFC) != (lastHeader[2] & 0xFC)) - { - dsyslog("dxr3: audiodecoder: found different audio header" - " (new: %#x, old: %#x), (re)initializing", - *((uint32_t*) lastHeader), *((uint32_t*) (buf+i))); - - Init(); - lastHeader[0] = buf[i]; - lastHeader[1] = buf[i+1]; - lastHeader[2] = buf[i+2]; - lastHeader[3] = buf[i+3]; - } - foundHeader = true; - } + for (i = 0; i < length-4 && !foundHeader; i++) { + unsigned int tempHead = *((unsigned int*)(buf+i)); + if (HeadCheck(tempHead)) { + if ((buf[i+2] & 0xFC) != (lastHeader[2] & 0xFC)) { + dsyslog("dxr3: audiodecoder: found different audio header" + " (new: %#x, old: %#x), (re)initializing", + *((uint32_t*) lastHeader), *((uint32_t*) (buf+i))); + + Init(); + lastHeader[0] = buf[i]; + lastHeader[1] = buf[i+1]; + lastHeader[2] = buf[i+2]; + lastHeader[3] = buf[i+3]; + } + foundHeader = true; + } } - if (audioSynched) - { - // no header found - decodeAudio = true; - } - else - { - if (foundHeader && pts) - { - decodeAudio = true; - audioSynched = true; - } + if (audioSynched) { + // no header found + decodeAudio = true; + } else { + if (foundHeader && pts) + { + decodeAudio = true; + audioSynched = true; + } } - try - { - while (length > 0 && decodeAudio) - { + try { + while (length > 0 && decodeAudio) { #if LIBAVCODEC_VERSION_INT < ((51<<16)+(29<<8)+0) - len = avcodec_decode_audio( + len = avcodec_decode_audio( #else - len = avcodec_decode_audio2( + len = avcodec_decode_audio2( #endif - contextAudio, (short *)(&pcmbuf), &out_size, - const_cast<uint8_t *>(buf), length); - if (len < 0 || out_size < 0) - throw WRONG_LENGTH; - - if (out_size) - { - cFixedLengthFrame* pTempFrame = aBuf.Push(pcmbuf, - out_size, pts); - if (pTempFrame) - { - // TODO: should we break out of the loop on push timeout? - pTempFrame->SetChannelCount(contextAudio->channels); - pTempFrame->SetSampleRate(contextAudio->sample_rate); - } - } - length -= len; - buf += len; - } - } - catch (audioException ex) - { - switch (ex) - { - case WRONG_LENGTH: - esyslog("dxr3: audiodecoder: wrong length"); - break; - - default: - esyslog("dxr3: audiodecoder: unexpected exception"); - break; - } - esyslog("dxr3: audiodecoder: skipping %d broken data bytes", length); - - Init(); + contextAudio, (short *)(&pcmbuf), &out_size, + const_cast<uint8_t *>(buf), length); + if (len < 0 || out_size < 0) + throw WRONG_LENGTH; + + if (out_size) { + cFixedLengthFrame* pTempFrame = aBuf.Push(pcmbuf, + out_size, pts); + if (pTempFrame) { + // TODO: should we break out of the loop on push timeout? + pTempFrame->SetChannelCount(contextAudio->channels); + pTempFrame->SetSampleRate(contextAudio->sample_rate); + } + } + length -= len; + buf += len; + } + } catch (audioException ex) { + switch (ex) { + case WRONG_LENGTH: + esyslog("dxr3: audiodecoder: wrong length"); + break; + + default: + esyslog("dxr3: audiodecoder: unexpected exception"); + break; + } + + esyslog("dxr3: audiodecoder: skipping %d broken data bytes", length); + Init(); } } @@ -200,53 +187,48 @@ void cDxr3AudioDecoder::DecodeLpcm(cDxr3PesFrame *frame, uint32_t pts, cDxr3Sync const uint8_t *buf = frame->GetPayload(); int length = frame->GetPayloadLength(); - if (length > (LPCM_HEADER_LENGTH + 2)) - { - // only even number of bytes are allowed - if ((length - LPCM_HEADER_LENGTH) % 2 != 0) - { - esyslog("dxr3: audiodecoder: skipping %d lpcm bytes", length); - return; - } - - uint8_t* pFrame = new uint8_t[length - LPCM_HEADER_LENGTH]; - for (int i = LPCM_HEADER_LENGTH; i < length; i += 2) - { - pFrame[i - LPCM_HEADER_LENGTH] = buf[i + 1]; - pFrame[i - LPCM_HEADER_LENGTH + 1] = buf[i]; - } - - int codedSpeed = (buf[5] >> 4) & 0x03; - int speed = 0; - - switch (codedSpeed) - { - case 1: - speed = 96000; - break; - - case 2: - speed = 44100; - break; - - case 3: - speed = 32000; - break; - - default: - speed = 48000; - break; - } - - cFixedLengthFrame* pTempFrame = aBuf.Push(pFrame, - length - LPCM_HEADER_LENGTH, - pts); - if (pTempFrame) - { - pTempFrame->SetChannelCount(1); - pTempFrame->SetSampleRate(speed); - } - delete[] pFrame; + if (length > (LPCM_HEADER_LENGTH + 2)) { + // only even number of bytes are allowed + if ((length - LPCM_HEADER_LENGTH) % 2 != 0) { + esyslog("dxr3: audiodecoder: skipping %d lpcm bytes", length); + return; + } + + uint8_t* pFrame = new uint8_t[length - LPCM_HEADER_LENGTH]; + for (int i = LPCM_HEADER_LENGTH; i < length; i += 2) { + pFrame[i - LPCM_HEADER_LENGTH] = buf[i + 1]; + pFrame[i - LPCM_HEADER_LENGTH + 1] = buf[i]; + } + + int codedSpeed = (buf[5] >> 4) & 0x03; + int speed = 0; + + switch (codedSpeed) { + case 1: + speed = 96000; + break; + + case 2: + speed = 44100; + break; + + case 3: + speed = 32000; + break; + + default: + speed = 48000; + break; + } + + cFixedLengthFrame* pTempFrame = aBuf.Push(pFrame, + length - LPCM_HEADER_LENGTH, + pts); + if (pTempFrame) { + pTempFrame->SetChannelCount(1); + pTempFrame->SetSampleRate(speed); + } + delete[] pFrame; } } @@ -263,23 +245,21 @@ void cDxr3AudioDecoder::DecodeAc3Dts(const uint8_t* pPes, const uint8_t* buf, ac3dtsDecoder.Encapsulate(pBuf + headerLength, length); cFrame* pFrame = 0; - while ((pFrame = rbuf.Get())) - { - if (pFrame && pFrame->Count()) - { - cDxr3PesFrame tempPes; - tempPes.parse(pFrame->Data(), pFrame->Count()); - int pesHeaderLength = (int) (tempPes.GetPayload() - tempPes.GetPesStart()); - uint8_t* pData = pFrame->Data() + pesHeaderLength + LPCM_HEADER_LENGTH; - - for (int i = 0; i < pFrame->Count() - pesHeaderLength - LPCM_HEADER_LENGTH; i += 2) - { - std::swap(pData[i], pData[i + 1]); - } - - aBuf.Push(pFrame->Data() + pesHeaderLength + LPCM_HEADER_LENGTH, pFrame->Count() - pesHeaderLength - 7, tempPes.GetPts()); - if (pFrame) rbuf.Drop(pFrame); - } + while ((pFrame = rbuf.Get())) { + if (pFrame && pFrame->Count()) { + cDxr3PesFrame tempPes; + tempPes.parse(pFrame->Data(), pFrame->Count()); + int pesHeaderLength = (int) (tempPes.GetPayload() - tempPes.GetPesStart()); + uint8_t* pData = pFrame->Data() + pesHeaderLength + LPCM_HEADER_LENGTH; + + for (int i = 0; i < pFrame->Count() - pesHeaderLength - LPCM_HEADER_LENGTH; i += 2) { + std::swap(pData[i], pData[i + 1]); + } + + aBuf.Push(pFrame->Data() + pesHeaderLength + LPCM_HEADER_LENGTH, pFrame->Count() - pesHeaderLength - 7, tempPes.GetPts()); + if (pFrame) + rbuf.Drop(pFrame); + } } } @@ -290,25 +270,16 @@ bool cDxr3AudioDecoder::HeadCheck(unsigned long head) bool retval = false; uint8_t* phead = (uint8_t*) (&head); - if (phead[0] != 0xFF) - { - retval = false; - } - else if (phead[1] != 0xFC && phead[1] != 0xFE) - { - retval = false; - } - else if ((phead[2] & 0xF0) == 0xF0) - { - retval = false; - } - else if ((phead[2] & 0xC) == 0xC) - { - retval = false; - } - else - { - retval = true; + if (phead[0] != 0xFF) { + retval = false; + } else if (phead[1] != 0xFC && phead[1] != 0xFE) { + retval = false; + } else if ((phead[2] & 0xF0) == 0xF0) { + retval = false; + } else if ((phead[2] & 0xC) == 0xC) { + retval = false; + } else { + retval = true; } return retval; diff --git a/dxr3syncbuffer.c b/dxr3syncbuffer.c index d51e530..7712e6c 100644 --- a/dxr3syncbuffer.c +++ b/dxr3syncbuffer.c @@ -45,9 +45,8 @@ cFixedLengthFrame::cFixedLengthFrame() : // ================================== cFixedLengthFrame::~cFixedLengthFrame() { - if (m_pData) - { - delete[] m_pData; + if (m_pData) { + delete[] m_pData; } } @@ -59,10 +58,9 @@ void cFixedLengthFrame::Init(uint32_t lenght) m_pData = new uint8_t[lenght]; // allocation ok? - if (!m_pData) - { - esyslog("dxr3: fatal: unable to allocate memory for new frame"); - exit(1); + if (!m_pData) { + esyslog("dxr3: fatal: unable to allocate memory for new frame"); + exit(1); } } @@ -70,11 +68,10 @@ void cFixedLengthFrame::Init(uint32_t lenght) void cFixedLengthFrame::CopyFrame(const uint8_t* pStart, int length, uint32_t pts, eFrameType type) { - if (length > m_length) - { - delete[] m_pData; - m_pData = new uint8_t[length]; - m_length = length; + if (length > m_length) { + delete[] m_pData; + m_pData = new uint8_t[length]; + m_length = length; } m_type = type; m_count = length; @@ -115,16 +112,14 @@ cDxr3SyncBuffer::cDxr3SyncBuffer(int frameCount, int frameLength, m_pBuffer = new cFixedLengthFrame[frameCount]; // got we a valid m_pBuffer? - if (!m_pBuffer) - { - esyslog("dxr3: fatal: unable to allocate memory for new frame"); - exit(1); + if (!m_pBuffer) { + esyslog("dxr3: fatal: unable to allocate memory for new frame"); + exit(1); } // init our new m_pBuffer; - for (int i = 0; i < frameCount; i++) - { - m_pBuffer[i].Init(frameLength); + for (int i = 0; i < frameCount; i++) { + m_pBuffer[i].Init(frameLength); } // set some default values @@ -143,9 +138,8 @@ cDxr3SyncBuffer::cDxr3SyncBuffer(int frameCount, int frameLength, // ================================== cDxr3SyncBuffer::~cDxr3SyncBuffer() { - if (m_pBuffer) - { - delete[] m_pBuffer; + if (m_pBuffer) { + delete[] m_pBuffer; } } @@ -167,33 +161,30 @@ bool cDxr3SyncBuffer::Poll(int TimeoutMs) struct timeval tv_start, tv; m_bPollSync = true; gettimeofday(&tv_start, NULL); - if (m_demuxMode == DXR3_DEMUX_REPLAY_MODE) - { - if (Available() >= Size() - (Size()*BUFFER_LIMIT/100)) - { - m_bPollSync = true; - while ((Available() >= Size() - (Size()*BUFFER_LIMIT_2)/100) && - ((m_dxr3Device.GetSysClock() - currTime) < - ((uint32_t)TimeoutMs * (uint32_t)45))) - { - int d_s, d_us, ms; - m_bPutBlock = true; - EnableGet(); - WaitForPut(); - gettimeofday(&tv, NULL); - d_s = tv.tv_sec - tv_start.tv_sec; - d_us = tv.tv_usec - tv_start.tv_usec; - ms = d_s * 1000 + d_us / 1000; - if (ms > TimeoutMs * 2) { - esyslog("dxr3: sync: secondary timeout"); - break; - } - } - if (Available() >= Size() - (Size()*BUFFER_LIMIT_2)/100) - { - retVal = false; - } - } + if (m_demuxMode == DXR3_DEMUX_REPLAY_MODE) { + if (Available() >= Size() - (Size()*BUFFER_LIMIT/100)) { + m_bPollSync = true; + while ((Available() >= Size() - (Size()*BUFFER_LIMIT_2)/100) && + ((m_dxr3Device.GetSysClock() - currTime) < + ((uint32_t)TimeoutMs * (uint32_t)45))) + { + int d_s, d_us, ms; + m_bPutBlock = true; + EnableGet(); + WaitForPut(); + gettimeofday(&tv, NULL); + d_s = tv.tv_sec - tv_start.tv_sec; + d_us = tv.tv_usec - tv_start.tv_usec; + ms = d_s * 1000 + d_us / 1000; + if (ms > TimeoutMs * 2) { + esyslog("dxr3: sync: secondary timeout"); + break; + } + } + if (Available() >= Size() - (Size()*BUFFER_LIMIT_2)/100) { + retVal = false; + } + } } return retVal; @@ -206,51 +197,47 @@ cFixedLengthFrame* cDxr3SyncBuffer::Push(const uint8_t* pStart, int length, uint struct timeval tv_start, tv; gettimeofday(&tv_start, NULL); - switch (m_demuxMode) - { + switch (m_demuxMode) { case DXR3_DEMUX_TRICK_MODE: - break; + break; case DXR3_DEMUX_TV_MODE: case DXR3_DEMUX_REPLAY_MODE: default: - while ((Available() >= Size() - (Size()*10)/100)) - { - int d_s, d_us, ms; - m_bPutBlock = true; - EnableGet(); - WaitForPut(); - gettimeofday(&tv, NULL); - d_s = tv.tv_sec - tv_start.tv_sec; - d_us = tv.tv_usec - tv_start.tv_usec; - ms = d_s * 1000 + d_us / 1000; - if (ms > 2000) { - esyslog("dxr3: sync: push timeout"); - return NULL; - } - } - - lastIndex = m_nextFree; - m_pBuffer[m_nextFree].CopyFrame(pStart, length, pts, type); - m_pBuffer[m_nextFree].SetChannelCount(UNKNOWN_CHANNEL_COUNT); - m_pBuffer[m_nextFree].SetSampleRate(UNKNOWN_DATA_RATE); - m_pBuffer[m_nextFree].SetAspectRatio(UNKNOWN_ASPECT_RATIO); - m_nextFree++; - m_count++; - m_nextFree %= Size(); - - if (m_nextFree == m_next) - { - esyslog("dxr3: sync: push buffer overrun"); - Clear(); // XXX This is only a workaround until a sufficient control algorithm is implemented - throw(SYNC_BUFFER_OVERRUN); - } - if (m_bStartReceiver) - { - EnableGet(); - } - break; + while ((Available() >= Size() - (Size()*10)/100)) { + int d_s, d_us, ms; + m_bPutBlock = true; + EnableGet(); + WaitForPut(); + gettimeofday(&tv, NULL); + d_s = tv.tv_sec - tv_start.tv_sec; + d_us = tv.tv_usec - tv_start.tv_usec; + ms = d_s * 1000 + d_us / 1000; + if (ms > 2000) { + esyslog("dxr3: sync: push timeout"); + return NULL; + } + } + + lastIndex = m_nextFree; + m_pBuffer[m_nextFree].CopyFrame(pStart, length, pts, type); + m_pBuffer[m_nextFree].SetChannelCount(UNKNOWN_CHANNEL_COUNT); + m_pBuffer[m_nextFree].SetSampleRate(UNKNOWN_DATA_RATE); + m_pBuffer[m_nextFree].SetAspectRatio(UNKNOWN_ASPECT_RATIO); + m_nextFree++; + m_count++; + m_nextFree %= Size(); + + if (m_nextFree == m_next) { + esyslog("dxr3: sync: push buffer overrun"); + Clear(); // XXX This is only a workaround until a sufficient control algorithm is implemented + throw(SYNC_BUFFER_OVERRUN); + } + if (m_bStartReceiver) { + EnableGet(); + } + break; } return &m_pBuffer[lastIndex]; @@ -275,23 +262,18 @@ cFixedLengthFrame* cDxr3SyncBuffer::Get(void) { cFixedLengthFrame* pRet = 0; - if (!m_bStopped) - { - while ((!Available() || !m_bStartReceiver) && !m_bStopped) - { - m_bGetBlock = true; - ReceiverStopped(); - WaitForGet(); - } - - if (m_nextFree != m_next) - { - pRet = &m_pBuffer[m_next]; - } - } - else - { - WaitForGet(); + if (!m_bStopped) { + while ((!Available() || !m_bStartReceiver) && !m_bStopped) { + m_bGetBlock = true; + ReceiverStopped(); + WaitForGet(); + } + + if (m_nextFree != m_next) { + pRet = &m_pBuffer[m_next]; + } + } else { + WaitForGet(); } return pRet; @@ -305,10 +287,9 @@ void cDxr3SyncBuffer::Clear(void) m_count = 0; m_bStartReceiver = false; m_bPollSync = false; - if (m_bPutBlock) - { - EnablePut(); - m_bPutBlock = false; + if (m_bPutBlock) { + EnablePut(); + m_bPutBlock = false; } } @@ -317,17 +298,15 @@ void cDxr3SyncBuffer::Start(void) { m_bStartReceiver = true; m_bStopped = false; - if (Available()) - { - EnableGet(); + if (Available()) { + EnableGet(); } } // ================================== void cDxr3SyncBuffer::WakeUp(void) { - if (m_bStartReceiver == true) - { + if (m_bStartReceiver == true) { EnableGet(); } } @@ -335,11 +314,10 @@ void cDxr3SyncBuffer::WakeUp(void) // ================================== void cDxr3SyncBuffer::WaitForReceiverStopped(void) { - if (!m_bGetBlock) - { - receiverStoppedMutex.Lock(); - receiverStopped.Wait(receiverStoppedMutex); - receiverStoppedMutex.Unlock(); + if (!m_bGetBlock) { + receiverStoppedMutex.Lock(); + receiverStopped.Wait(receiverStoppedMutex); + receiverStoppedMutex.Unlock(); } } |