summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Reufer <thomas@reufer.ch>2014-10-28 13:38:14 +0100
committerThomas Reufer <thomas@reufer.ch>2014-10-29 17:03:49 +0100
commit4cf6d20b20e4faa5b51bb515ffd2d015d93dc549 (patch)
treed2fd9e108227e64dd0bd23a4cb9e46fc35107257
parentaaacdf7c87413cb52fcdb70937bb25a243a085f2 (diff)
downloadvdr-plugin-rpihddevice-4cf6d20b20e4faa5b51bb515ffd2d015d93dc549.tar.gz
vdr-plugin-rpihddevice-4cf6d20b20e4faa5b51bb515ffd2d015d93dc549.tar.bz2
added DTS audio codec support
-rw-r--r--HISTORY1
-rw-r--r--audio.c140
-rw-r--r--audio.h2
-rw-r--r--omx.c21
-rw-r--r--omx.h3
-rw-r--r--tools.h4
6 files changed, 153 insertions, 18 deletions
diff --git a/HISTORY b/HISTORY
index 9a1363a..dcba2c4 100644
--- a/HISTORY
+++ b/HISTORY
@@ -2,6 +2,7 @@ VDR Plugin 'rpihddevice' Revision History
-----------------------------------------
- new:
+ - added DTS audio codec support
- set HDMI speaker layout to fix channel mapping for multi channel PCM output
- support building against external ffmpeg/libav by setting EXT_LIBAV
- support for >=ffmpeg-1.2 and >=libav-0.8 with resampling
diff --git a/audio.c b/audio.c
index 733fd6b..7ec524e 100644
--- a/audio.c
+++ b/audio.c
@@ -44,6 +44,7 @@ extern "C" {
# define AV_CODEC_ID_AC3 CODEC_ID_AC3
# define AV_CODEC_ID_EAC3 CODEC_ID_EAC3
# define AV_CODEC_ID_AAC CODEC_ID_AAC
+# define AV_CODEC_ID_DTS CODEC_ID_DTS
#endif
#if LIBAVCODEC_VERSION_MAJOR < 54
@@ -119,6 +120,17 @@ public:
return m_samplingRate;
}
+ unsigned int GetFrameSize(void)
+ {
+ m_mutex->Lock();
+
+ if (!m_parsed)
+ Parse();
+
+ m_mutex->Unlock();
+ return m_packet.size;
+ }
+
uint64_t GetPts(void)
{
uint64_t pts = 0;
@@ -263,12 +275,12 @@ private:
unsigned int frameSize = 0;
unsigned int samplingRate = 0;
- while (m_size - offset >= 3)
+ while (m_size - offset >= 4)
{
- // 4 bytes 0xFFExxxxx MPEG audio
- // 5 bytes 0x0B77xxxxxx AC-3 audio
- // 6 bytes 0x0B77xxxxxxxx E-AC-3 audio
- // 7/9 bytes 0xFFFxxxxxxxxxxx AAC audio
+ // 0xFFE... MPEG audio
+ // 0x0B77... (E)AC-3 audio
+ // 0xFFF... AAC audio
+ // 0x7FFE8001... DTS audio
// PCM audio can't be found
const uint8_t *p = m_packet.data + offset;
@@ -294,6 +306,11 @@ private:
codec = cAudioCodec::eAAC;
break;
+ case cAudioCodec::eDTS:
+ if (DtsCheck(p, n, frameSize, channels, samplingRate))
+ codec = cAudioCodec::eDTS;
+ break;
+
default:
break;
}
@@ -302,7 +319,7 @@ private:
{
// if there is enough data in buffer, check if predicted next
// frame start is valid
- if (n < frameSize + 3 ||
+ if (n < frameSize + 4 ||
FastCheck(p + frameSize) != cAudioCodec::eInvalid)
{
// if codec has been detected but buffer does not yet
@@ -364,19 +381,21 @@ private:
static const uint32_t Mpeg4SampleRateTable[16];
static const uint16_t Ac3SampleRateTable[4];
static const uint16_t Ac3FrameSizeTable[38][3];
+ static const uint32_t DtsSampleRateTable[16];
static cAudioCodec::eCodec FastCheck(const uint8_t *p)
{
return FastMpegCheck(p) ? cAudioCodec::eMPG :
FastAc3Check (p) ? cAudioCodec::eAC3 :
FastAdtsCheck(p) ? cAudioCodec::eAAC :
+ FastDtsCheck (p) ? cAudioCodec::eDTS :
cAudioCodec::eInvalid;
}
///
/// Fast check for MPEG audio.
///
- /// 4 bytes 0xFFExxxxx MPEG audio
+ /// 0xFFE... MPEG audio
///
static bool FastMpegCheck(const uint8_t *p)
{
@@ -466,7 +485,7 @@ private:
///
/// Fast check for (E-)AC-3 audio.
///
- /// 5 bytes 0x0B77xxxxxx AC-3 audio
+ /// 0x0B77... AC-3 audio
///
static bool FastAc3Check(const uint8_t *p)
{
@@ -578,7 +597,7 @@ private:
///
/// Fast check for AAC LATM audio.
///
- /// 3 bytes 0x56Exxx AAC LATM audio
+ /// 0x56E... AAC LATM audio
///
static bool FastLatmCheck(const uint8_t *p)
{
@@ -618,7 +637,7 @@ private:
///
/// Fast check for ADTS Audio Data Transport Stream.
///
- /// 7/9 bytes 0xFFFxxxxxxxxxxx(xxxx) ADTS audio
+ /// 0xFFF... ADTS audio
///
static bool FastAdtsCheck(const uint8_t *p)
{
@@ -681,6 +700,91 @@ private:
return true;
}
+
+ ///
+ /// Fast check for DTS Audio Data Transport Stream.
+ ///
+ /// 0x7FFE8001.... DTS audio
+ ///
+ static bool FastDtsCheck(const uint8_t *p)
+ {
+ if (p[0] != 0x7F) // 32bit sync
+ return false;
+ if (p[1] != 0xFE)
+ return false;
+ if (p[2] != 0x80)
+ return false;
+ if (p[3] != 0x01)
+ return false;
+ return true;
+ }
+
+ ///
+ /// Check for DTS Audio Data Transport Stream.
+ ///
+ /// 0x7FFE8001 already checked.
+ ///
+ /// AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA BCCCCCDE EEEEEEFF FFFFFFFF FFFFGGGG
+ /// GGHHHHII IIIJKLMN OOOPQRRS TTTTTTTT TTTTTTTT UVVVVWWX XXYZaaaa
+ ///
+ /// o A*32 sync word 0x7FFE8001
+ /// o B*1 frame type
+ /// o C*5 deficit sample count
+ /// o D*1 CRC present flag
+ /// o E*7 number of PCM sample blocks
+ /// o F*14 primary frame size
+ /// o G*6 audio channel arrangement
+ /// o H*4 core audio sampling frequency
+ /// o I*5 transmission bit rate
+ /// o J*1 embedded downmix enabled
+ /// o K*1 embedded dynamic range flag
+ /// o L*1 embedded time stamp flag
+ /// o M*1 auxiliary data flag
+ /// o N*1 HDCD
+ /// o O*3 extension audio descriptor flag
+ /// o P*1 extended coding flag
+ /// o Q*1 audio sync word insertion flag
+ /// o R*2 low frequency effects flag
+ /// o S*1 predictor history flag
+ /// o T*16 header CRC check (if CRC present flag set)
+ /// o U*1 multi rate interpolator switch
+ /// o V*4 encoder software revision
+ /// o W*2 copy history
+ /// o X*3 source PCM resolution
+ /// o Y*1 front sum/difference flag
+ /// o Z*1 surrounds sum/difference flag
+ /// o a*4 dialog normalization parameter
+ ///
+ static bool DtsCheck(const uint8_t *p, unsigned int size,
+ unsigned int &frameSize, unsigned int &channels,
+ unsigned int &samplingRate)
+ {
+ frameSize = size;
+ if (size < 11)
+ return true;
+
+ frameSize = ((p[5] & 0x03) << 12) + (p[6] << 4) + ((p[7] & 0xF0) >> 4);
+ frameSize++;
+
+ samplingRate = DtsSampleRateTable[(p[8] & 0x3C) >> 2];
+
+ int amode = ((p[7] & 0x0F) << 2) + ((p[8] & 0xC0) >> 6);
+ channels =
+ amode == 0x00 ? 1 : // mono
+ amode == 0x02 ? 2 : // L, R
+ amode == 0x03 ? 2 : // (L + R), (L - R)
+ amode == 0x04 ? 2 : // LT, RT
+ amode == 0x05 ? 3 : // L, R, C
+ amode == 0x06 ? 3 : // L, R, S
+ amode == 0x08 ? 4 : // L, R, RL, RR
+ amode == 0x09 ? 5 : 0; // L, C, R, RL, RR
+
+ if (!samplingRate || !channels)
+ return false;
+
+ if (p[10] & 0x06) channels++;
+ return true;
+ }
};
///
@@ -741,6 +845,14 @@ const uint16_t cRpiAudioDecoder::cParser::Ac3FrameSizeTable[38][3] =
{1152, 1254, 1728}, {1280, 1393, 1920}, {1280, 1394, 1920},
};
+///
+/// DTS sample rate table.
+///
+const uint32_t cRpiAudioDecoder::cParser::DtsSampleRateTable[16] =
+ { 0, 8000, 16000, 32000, 64000,
+ 0, 11025, 22050, 44100, 88200,
+ 0, 12000, 24000, 48000, 96000, 0 };
+
/* ------------------------------------------------------------------------- */
#define AV_CH_LAYOUT(ch) ( \
@@ -799,6 +911,7 @@ int cRpiAudioDecoder::Init(void)
m_codecs[cAudioCodec::eAC3 ].codec = avcodec_find_decoder(AV_CODEC_ID_AC3);
m_codecs[cAudioCodec::eEAC3].codec = avcodec_find_decoder(AV_CODEC_ID_EAC3);
m_codecs[cAudioCodec::eAAC ].codec = avcodec_find_decoder(AV_CODEC_ID_AAC);
+ m_codecs[cAudioCodec::eDTS ].codec = avcodec_find_decoder(AV_CODEC_ID_DTS);
for (int i = 0; i < cAudioCodec::eNumCodecs; i++)
{
@@ -934,7 +1047,8 @@ void cRpiAudioDecoder::Action(void)
samplingRate = m_parser->GetSamplingRate();
outputChannels = channels;
- SetCodec(codec, outputChannels, samplingRate);
+ SetCodec(codec, outputChannels, samplingRate,
+ m_parser->GetFrameSize());
av_frame_unref(frame);
m_setupChanged = false;
@@ -1127,7 +1241,7 @@ void cRpiAudioDecoder::Action(void)
DLOG("cAudioDecoder() thread ended");
}
-void cRpiAudioDecoder::SetCodec(cAudioCodec::eCodec codec, unsigned int &channels, unsigned int samplingRate)
+void cRpiAudioDecoder::SetCodec(cAudioCodec::eCodec codec, unsigned int &channels, unsigned int samplingRate, unsigned int frameSize)
{
m_omx->StopAudio();
@@ -1168,7 +1282,7 @@ void cRpiAudioDecoder::SetCodec(cAudioCodec::eCodec codec, unsigned int &channel
#if FF_API_REQUEST_CHANNELS
m_codecs[codec].context->request_channels = channels;
#endif
- m_omx->SetupAudioRender(outputFormat, channels, outputPort, samplingRate);
+ m_omx->SetupAudioRender(outputFormat, channels, outputPort, samplingRate, frameSize);
ILOG("set %s audio output format to %dch %s, %d.%dkHz%s",
cRpiAudioPort::Str(outputPort), channels, cAudioCodec::Str(outputFormat),
samplingRate / 1000, (samplingRate % 1000) / 100,
diff --git a/audio.h b/audio.h
index d0da5db..ac7b838 100644
--- a/audio.h
+++ b/audio.h
@@ -33,7 +33,7 @@ protected:
virtual void Action(void);
void SetCodec(cAudioCodec::eCodec codec, unsigned int &channels,
- unsigned int samplingRate);
+ unsigned int samplingRate, unsigned int frameSize = 0);
static void OnAudioSetupChanged(void *data)
{ (static_cast <cRpiAudioDecoder*> (data))->HandleAudioSetupChanged(); }
diff --git a/omx.c b/omx.c
index 0e68a30..b5be01c 100644
--- a/omx.c
+++ b/omx.c
@@ -944,8 +944,9 @@ void cOmx::SetVideoDecoderExtraBuffers(int extraBuffers)
}
int cOmx::SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels,
- cRpiAudioPort::ePort audioPort, int samplingRate)
+ cRpiAudioPort::ePort audioPort, int samplingRate, int frameSize)
{
+ ELOG("%d", frameSize);
OMX_AUDIO_PARAM_PORTFORMATTYPE format;
OMX_INIT_STRUCT(format);
format.nPortIndex = 100;
@@ -959,7 +960,7 @@ int cOmx::SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels,
outputFormat == cAudioCodec::eAC3 ? OMX_AUDIO_CodingDDP :
outputFormat == cAudioCodec::eEAC3 ? OMX_AUDIO_CodingDDP :
outputFormat == cAudioCodec::eAAC ? OMX_AUDIO_CodingAAC :
- outputFormat == cAudioCodec::eAAC ? OMX_AUDIO_CodingAAC :
+ outputFormat == cAudioCodec::eDTS ? OMX_AUDIO_CodingDTS :
OMX_AUDIO_CodingAutoDetect;
if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eAudioRender]),
@@ -1009,6 +1010,22 @@ int cOmx::SetupAudioRender(cAudioCodec::eCodec outputFormat, int channels,
ELOG("failed to set audio render aac parameters!");
break;
+ case cAudioCodec::eDTS:
+ OMX_AUDIO_PARAM_DTSTYPE dts;
+ OMX_INIT_STRUCT(dts);
+ dts.nPortIndex = 100;
+ dts.nChannels = channels;
+ dts.nSampleRate = samplingRate;
+ dts.nDtsType = 1;
+ dts.nFormat = 3; /* 16bit, LE */
+ dts.nDtsFrameSizeBytes = frameSize;
+ OMX_AUDIO_CHANNEL_MAPPING(dts, channels);
+
+ if (OMX_SetParameter(ILC_GET_HANDLE(m_comp[eAudioRender]),
+ OMX_IndexParamAudioDts, &dts) != OMX_ErrorNone)
+ ELOG("failed to set audio render dts parameters!");
+ break;
+
case cAudioCodec::ePCM:
OMX_AUDIO_PARAM_PCMMODETYPE pcm;
OMX_INIT_STRUCT(pcm);
diff --git a/omx.h b/omx.h
index ea97561..cdd08ef 100644
--- a/omx.h
+++ b/omx.h
@@ -85,7 +85,8 @@ public:
int SetVideoCodec(cVideoCodec::eCodec codec,
eDataUnitType dataUnit = eArbitraryStreamSection);
int SetupAudioRender(cAudioCodec::eCodec outputFormat,
- int channels, cRpiAudioPort::ePort audioPort, int samplingRate = 0);
+ int channels, cRpiAudioPort::ePort audioPort,
+ int samplingRate = 0, int frameSize = 0);
void GetVideoFormat(int &width, int &height, int &frameRate,
bool &interlaced);
diff --git a/tools.h b/tools.h
index fdfa528..39890ea 100644
--- a/tools.h
+++ b/tools.h
@@ -96,6 +96,7 @@ public:
eAC3,
eEAC3,
eAAC,
+ eDTS,
eNumCodecs,
eInvalid
};
@@ -105,7 +106,8 @@ public:
(codec == eMPG) ? "MPEG" :
(codec == eAC3) ? "AC3" :
(codec == eEAC3) ? "E-AC3" :
- (codec == eAAC) ? "AAC" : "unknown";
+ (codec == eAAC) ? "AAC" :
+ (codec == eDTS) ? "DTS" : "unknown";
}
};