summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Reufer <thomas@reufer.ch>2014-03-23 10:07:56 +0100
committerThomas Reufer <thomas@reufer.ch>2014-03-23 10:07:56 +0100
commit0c2e145ce8510204d488567b16e26e3053b0279e (patch)
tree5aaf390c7c65d889024a521ae35a4355617c8e4b
parentf9b1bcff899ffb505ec3e65bed6aea22bf9d22a5 (diff)
downloadvdr-plugin-rpihddevice-0c2e145ce8510204d488567b16e26e3053b0279e.tar.gz
vdr-plugin-rpihddevice-0c2e145ce8510204d488567b16e26e3053b0279e.tar.bz2
added proper buffering at audio parser and reduced OMX audio buffers
-rw-r--r--audio.c100
-rw-r--r--audio.h4
-rw-r--r--omx.c2
-rw-r--r--omxdevice.c2
4 files changed, 60 insertions, 48 deletions
diff --git a/audio.c b/audio.c
index 73721c0..52ab22e 100644
--- a/audio.c
+++ b/audio.c
@@ -11,9 +11,10 @@
#include <vdr/tools.h>
#include <vdr/remux.h>
+#include <queue>
#include <string.h>
-#define AVPKT_BUFFER_SIZE (64 * 1024) /* 1 PES packet */
+#define AVPKT_BUFFER_SIZE (KILOBYTE(256))
class cAudioParser
{
@@ -56,6 +57,16 @@ public:
return m_samplingRate;
}
+ uint64_t GetPts(void)
+ {
+ return m_ptsQueue.empty() ? 0 : m_ptsQueue.front().pts;
+ }
+
+ unsigned int GetFreeSpace(void)
+ {
+ return AVPKT_BUFFER_SIZE - m_size - FF_INPUT_BUFFER_PADDING_SIZE;
+ }
+
bool Empty(void)
{
if (!m_parsed)
@@ -88,9 +99,12 @@ public:
m_size = 0;
m_parsed = false;
memset(m_packet.data, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+
+ while (!m_ptsQueue.empty())
+ m_ptsQueue.pop();
}
- bool Append(const unsigned char *data, unsigned int length)
+ bool Append(const unsigned char *data, uint64_t pts, unsigned int length)
{
m_mutex->Lock();
bool ret = true;
@@ -102,6 +116,10 @@ public:
memcpy(m_packet.data + m_size, data, length);
m_size += length;
memset(m_packet.data + m_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+
+ Pts entry = {pts, length};
+ m_ptsQueue.push(entry);
+
m_parsed = false;
}
m_mutex->Unlock();
@@ -118,6 +136,25 @@ public:
m_size -= length;
memset(m_packet.data + m_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+ // clear current PTS since it's not valid anymore after
+ // shrinking the packet
+ if (!m_ptsQueue.empty())
+ m_ptsQueue.front().pts = 0;
+
+ while (!m_ptsQueue.empty() && length)
+ {
+ if (m_ptsQueue.front().length <= length)
+ {
+ length -= m_ptsQueue.front().length;
+ m_ptsQueue.pop();
+ }
+ else
+ {
+ length -= m_ptsQueue.front().length -= length;
+ length = 0;
+ }
+ }
+
m_parsed = false;
}
else
@@ -218,12 +255,19 @@ private:
m_mutex->Unlock();
}
+ struct Pts
+ {
+ uint64_t pts;
+ unsigned int length;
+ };
+
cMutex* m_mutex;
AVPacket m_packet;
cAudioCodec::eCodec m_codec;
unsigned int m_channels;
unsigned int m_samplingRate;
unsigned int m_size;
+ std::queue<Pts> m_ptsQueue;
bool m_parsed;
/* ------------------------------------------------------------------------- */
@@ -605,8 +649,6 @@ cAudioDecoder::cAudioDecoder(cOmx *omx) :
cThread(),
m_passthrough(false),
m_reset(false),
- m_ready(false),
- m_pts(0),
m_wait(new cCondWait()),
m_parser(new cAudioParser()),
m_omx(omx)
@@ -631,7 +673,7 @@ int cAudioDecoder::Init(void)
m_codecs[cAudioCodec::eMPG ].codec = avcodec_find_decoder(CODEC_ID_MP3);
m_codecs[cAudioCodec::eAC3 ].codec = avcodec_find_decoder(CODEC_ID_AC3);
m_codecs[cAudioCodec::eEAC3].codec = avcodec_find_decoder(CODEC_ID_EAC3);
- m_codecs[cAudioCodec::eAAC].codec = avcodec_find_decoder(CODEC_ID_AAC);
+ m_codecs[cAudioCodec::eAAC ].codec = avcodec_find_decoder(CODEC_ID_AAC);
for (int i = 0; i < cAudioCodec::eNumCodecs; i++)
{
@@ -690,27 +732,14 @@ int cAudioDecoder::DeInit(void)
}
bool cAudioDecoder::WriteData(const unsigned char *buf, unsigned int length,
- uint64_t pts, bool force)
+ uint64_t pts)
{
Lock();
- bool ret = false;
- // normally, only accept new audio packet if parser is empty. appending
- // new data may be forced in transfer mode, can't be tracked in this case
- if (m_ready || force)
- {
- if (m_parser->Append(buf, length))
- {
- if (m_ready)
- m_pts = pts;
- else
- DBG("audio parser not empty, pts discarded");
+ bool ret = m_parser->Append(buf, pts, length);
+ if (ret)
+ m_wait->Signal();
- m_ready = false;
- m_wait->Signal();
- ret = true;
- }
- }
Unlock();
return ret;
}
@@ -729,7 +758,7 @@ void cAudioDecoder::Reset(void)
bool cAudioDecoder::Poll(void)
{
- return m_ready;
+ return m_parser->GetFreeSpace() > KILOBYTE(16);
}
void cAudioDecoder::Action(void)
@@ -751,8 +780,6 @@ void cAudioDecoder::Action(void)
return;
}
- m_ready = true;
-
while (Running())
{
setupChanged |= cRpiSetup::HasAudioSetupChanged();
@@ -783,14 +810,11 @@ void cAudioDecoder::Action(void)
// get free buffer
while ((!m_parser->Empty() || frame->nb_samples) && !buf && !m_reset)
{
- buf = m_omx->GetAudioBuffer(m_pts);
+ buf = m_omx->GetAudioBuffer(m_parser->GetPts());
if (!buf)
m_wait->Wait(10);
else
- {
- m_pts = 0;
buf->nFilledLen = 0;
- }
}
// decoding loop
@@ -883,24 +907,14 @@ void cAudioDecoder::Action(void)
}
// -- empty buffer --
- if (buf)
- {
- if (buf->nFilledLen)
- m_omx->SetClockReference(cOmx::eClockRefAudio);
- if (m_omx->EmptyAudioBuffer(buf))
- buf = 0;
- }
+ if (buf && m_omx->EmptyAudioBuffer(buf))
+ buf = 0;
m_reset = false;
- // accept new packets as soon as parser is empty and frame has been sent
+ // wait for new audio packets
if (m_parser->Empty() && !frame->nb_samples)
- {
- if (m_ready)
- m_wait->Wait(50);
- else
- m_ready = true;
- }
+ m_wait->Wait(50);
}
av_free(frame);
diff --git a/audio.h b/audio.h
index 7a8c0c5..8647e4d 100644
--- a/audio.h
+++ b/audio.h
@@ -30,7 +30,7 @@ public:
virtual int DeInit(void);
virtual bool WriteData(const unsigned char *buf, unsigned int length,
- uint64_t pts = 0, bool force = false);
+ uint64_t pts = 0);
virtual bool Poll(void);
virtual void Reset(void);
@@ -52,8 +52,6 @@ private:
Codec m_codecs[cAudioCodec::eNumCodecs];
bool m_passthrough;
bool m_reset;
- bool m_ready;
- uint64_t m_pts;
cCondWait *m_wait;
cAudioParser *m_parser;
diff --git a/omx.c b/omx.c
index 2ae7b8b..4009d94 100644
--- a/omx.c
+++ b/omx.c
@@ -974,7 +974,7 @@ int cOmx::SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels,
ELOG("failed to get audio render port parameters!");
param.nBufferSize = KILOBYTE(160);
- param.nBufferCountActual = 8;
+ param.nBufferCountActual = 4;
m_freeAudioBuffers = param.nBufferCountActual;
if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eAudioRender]),
diff --git a/omxdevice.c b/omxdevice.c
index 54e7010..716cf89 100644
--- a/omxdevice.c
+++ b/omxdevice.c
@@ -200,7 +200,7 @@ int cOmxDevice::PlayAudio(const uchar *Data, int Length, uchar Id)
UpdateLatency(pts);
int ret = m_audio->WriteData(Data + PesPayloadOffset(Data),
- Length - PesPayloadOffset(Data), pts, Transferring()) ? Length : 0;
+ Length - PesPayloadOffset(Data), pts) ? Length : 0;
if (Transferring() && !ret)
DLOG("audio packet not accepted! (%d bytes)", Length);