summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Reufer <thomas@reufer.ch>2014-09-26 10:19:26 +0200
committerThomas Reufer <thomas@reufer.ch>2014-09-26 10:19:26 +0200
commitf15d6ed1587112728dba4412091cfff53a60f7d0 (patch)
tree9918e21d9e009a9c7fa99c03548cdbe1d7451259
parent3ad56849c844760dd8317a13f2a2b8b69f3feabc (diff)
downloadvdr-plugin-rpihddevice-f15d6ed1587112728dba4412091cfff53a60f7d0.tar.gz
vdr-plugin-rpihddevice-f15d6ed1587112728dba4412091cfff53a60f7d0.tar.bz2
reworked audio decoding loop and set correct dstSize before resampling
-rw-r--r--HISTORY2
-rw-r--r--audio.c175
2 files changed, 107 insertions, 70 deletions
diff --git a/HISTORY b/HISTORY
index 854d19b..2cbcc4d 100644
--- a/HISTORY
+++ b/HISTORY
@@ -10,6 +10,8 @@ VDR Plugin 'rpihddevice' Revision History
- reworked setup parameter handling
- implemented proper command queue for OVG-OSD
- fixed:
+ - reworked audio decoding loop and set correct dstSize before resampling
+ - avoid flushing OMX video chain twice when calling SetPlayMode(pmNone)
- skip packets with invalid payload offset in PlayVideo() and PlayAudio()
- play multiple video PES packets sequentially in StillPicture()
- updated parameter when setting clock latency target according omxplayer
diff --git a/audio.c b/audio.c
index f7b2513..508556d 100644
--- a/audio.c
+++ b/audio.c
@@ -88,22 +88,34 @@ public:
cAudioCodec::eCodec GetCodec(void)
{
+ m_mutex->Lock();
+
if (!m_parsed)
Parse();
+
+ m_mutex->Unlock();
return m_codec;
}
unsigned int GetChannels(void)
{
+ m_mutex->Lock();
+
if (!m_parsed)
Parse();
+
+ m_mutex->Unlock();
return m_channels;
}
unsigned int GetSamplingRate(void)
{
+ m_mutex->Lock();
+
if (!m_parsed)
Parse();
+
+ m_mutex->Unlock();
return m_samplingRate;
}
@@ -126,8 +138,12 @@ public:
bool Empty(void)
{
+ m_mutex->Lock();
+
if (!m_parsed)
Parse();
+
+ m_mutex->Unlock();
return m_packet.size == 0;
}
@@ -241,7 +257,6 @@ private:
void Parse()
{
- m_mutex->Lock();
cAudioCodec::eCodec codec = cAudioCodec::eInvalid;
unsigned int channels = 0;
unsigned int offset = 0;
@@ -305,7 +320,7 @@ private:
if (offset)
{
- DLOG("audio parser skipped %u of %u bytes", offset, m_size);
+ DBG("audio parser skipped %u of %u bytes", offset, m_size);
Shrink(offset);
}
@@ -320,7 +335,6 @@ private:
m_packet.size = 0;
m_parsed = true;
- m_mutex->Unlock();
}
struct Pts
@@ -950,8 +964,37 @@ void cRpiAudioDecoder::Action(void)
samplingRate != m_parser->GetSamplingRate()))
break;
- // -- decode frame --
- if (!frame->nb_samples && !m_passthrough)
+ if (m_passthrough)
+ {
+ int len = m_parser->Packet()->size;
+
+ // enough space in current buffer?
+ if (len <= (signed)(buf->nAllocLen - buf->nFilledLen))
+ {
+ // rise reset flag if packet is even bigger than
+ // allocated buffer
+ m_reset = len > (signed)(buf->nAllocLen) || len < 0;
+ if (m_reset)
+ ELOG("encoded audio frame too big!");
+ break;
+ }
+ // for pass-through directly copy AV packet to buffer
+ memcpy(buf->pBuffer + buf->nFilledLen,
+ m_parser->Packet()->data, len);
+
+ buf->nFilledLen += len;
+ m_parser->Shrink(len);
+
+ // if there's a valid PTS after shrinking, a complete PES packet
+ // has been handled and is ready to play
+ if (m_parser->GetPts())
+ break;
+
+ continue;
+ }
+
+ // if all samples have been copied, decode new frame
+ if (!frame->nb_samples)
{
// if frame has been emptied, decode new data, rise reset
// flag if something goes wrong
@@ -960,8 +1003,7 @@ void cRpiAudioDecoder::Action(void)
frame, &gotFrame, m_parser->Packet());
if (len > 0)
m_parser->Shrink(len);
-
- if (len < 0)
+ else
{
ELOG("failed to decode audio frame!");
m_reset = true;
@@ -969,77 +1011,65 @@ void cRpiAudioDecoder::Action(void)
}
}
- // -- get length --
- int len = m_passthrough ? m_parser->Packet()->size :
- av_samples_get_buffer_size(NULL, outputChannels,
- frame->nb_samples, AV_SAMPLE_FMT_S16, 1);
-
-#ifdef DO_RESAMPLE
- if (sampleFormat != m_codecs[codec].context->sample_fmt)
+ if (frame->nb_samples)
{
- sampleFormat = m_codecs[codec].context->sample_fmt;
- swr_free(&resample);
- resample = swr_alloc();
-
- if (!resample)
+#ifdef DO_RESAMPLE
+ // setup resampler if needed
+ if (sampleFormat != m_codecs[codec].context->sample_fmt)
{
- ELOG("failed to allocate resampling context!");
- m_reset = true;
- break;
+ sampleFormat = m_codecs[codec].context->sample_fmt;
+ swr_free(&resample);
+ resample = swr_alloc();
+
+ if (!resample)
+ {
+ ELOG("failed to allocate resampling context!");
+ m_reset = true;
+ break;
+ }
+
+ DBG("decoding %s samples in %d channels",
+ AV_SAMPLE_STR(sampleFormat),
+ m_codecs[codec].context->channels);
+
+ av_opt_set_int(resample, "in_channel_layout",
+ AV_CH_LAYOUT(m_codecs[codec].context->channels), 0);
+ av_opt_set_int(resample, "out_channel_layout",
+ AV_CH_LAYOUT(outputChannels), 0);
+
+ av_opt_set_int(resample, "in_sample_rate",
+ m_codecs[codec].context->sample_rate, 0);
+ av_opt_set_int(resample, "out_sample_rate",
+ m_codecs[codec].context->sample_rate, 0);
+
+ av_opt_set_int(resample, "in_sample_fmt",
+ m_codecs[codec].context->sample_fmt, 0);
+ av_opt_set_int(resample, "out_sample_fmt",
+ AV_SAMPLE_FMT_S16, 0);
+
+ swr_init(resample);
}
- DBG("decoding %s samples in %d channels",
- AV_SAMPLE_STR(sampleFormat),
- m_codecs[codec].context->channels);
-
- av_opt_set_int(resample, "in_channel_layout",
- AV_CH_LAYOUT(m_codecs[codec].context->channels), 0);
- av_opt_set_int(resample, "out_channel_layout",
- AV_CH_LAYOUT(outputChannels), 0);
-
- av_opt_set_int(resample, "in_sample_rate",
- m_codecs[codec].context->sample_rate, 0);
- av_opt_set_int(resample, "out_sample_rate",
- m_codecs[codec].context->sample_rate, 0);
-
- av_opt_set_int(resample, "in_sample_fmt",
- m_codecs[codec].context->sample_fmt, 0);
- av_opt_set_int(resample, "out_sample_fmt",
- AV_SAMPLE_FMT_S16, 0);
-
- swr_init(resample);
- }
-#endif
- if (len > (signed)(buf->nAllocLen - buf->nFilledLen) || len < 0)
- {
- // rise reset flag if packet is even bigger than allocated buffer
- m_reset = len > (signed)(buf->nAllocLen) || len < 0;
- if (m_reset)
- ELOG("encoded audio frame too big!");
- break;
- }
-
- // -- copy frame --
- if (m_passthrough)
- {
- // for pass-through directly copy AV packet to buffer
- memcpy(buf->pBuffer + buf->nFilledLen,
- m_parser->Packet()->data, len);
-
- buf->nFilledLen += len;
- m_parser->Shrink(len);
- }
- else if (frame->nb_samples)
- {
-#ifdef DO_RESAMPLE
+ // now do the resampling
uint8_t *dst[] = { buf->pBuffer + buf->nFilledLen };
const uint8_t** src = (const uint8_t **)(frame->extended_data);
+ int dstSize = (buf->nAllocLen - buf->nFilledLen) /
+ (outputChannels *
+ av_get_bytes_per_sample(AV_SAMPLE_FMT_S16));
+
+ int copiedSamples = swr_convert(resample,
+ dst, dstSize, src, frame->nb_samples);
- if (swr_convert(resample,
- dst, frame->nb_samples, src, frame->nb_samples) > 0)
+ av_frame_unref(frame);
+
+ if (copiedSamples > 0)
{
- buf->nFilledLen += len;
- av_frame_unref(frame);
+ buf->nFilledLen += av_samples_get_buffer_size(NULL,
+ outputChannels, copiedSamples, AV_SAMPLE_FMT_S16, 1);
+
+ // get new buffer if not all samples have been resampled
+ if (copiedSamples != frame->nb_samples)
+ break;
}
else
{
@@ -1048,6 +1078,11 @@ void cRpiAudioDecoder::Action(void)
break;
}
#else
+ // -- get length --
+ int len = m_passthrough ? m_parser->Packet()->size :
+ av_samples_get_buffer_size(NULL, outputChannels,
+ frame->nb_samples, AV_SAMPLE_FMT_S16, 1);
+
memcpy(buf->pBuffer + buf->nFilledLen, frame->data[0], len);
buf->nFilledLen += len;
av_frame_unref(frame);