summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohns <johns98@gmx.net>2012-01-07 03:05:43 +0100
committerJohns <johns98@gmx.net>2012-01-07 03:05:43 +0100
commit45a34a33811123eaf8f3d35f246f79c9219a30a6 (patch)
tree4b4519eb7e5603b2c002a37caa23b1fb4851eeff
parent92ffd978b00e1d7138fc965edbf84032192f3fbd (diff)
downloadvdr-plugin-softhddevice-45a34a33811123eaf8f3d35f246f79c9219a30a6.tar.gz
vdr-plugin-softhddevice-45a34a33811123eaf8f3d35f246f79c9219a30a6.tar.bz2
Add support for ac3 audio pass through.
-rw-r--r--ChangeLog2
-rw-r--r--README.txt4
-rw-r--r--codec.c196
-rw-r--r--softhddevice.cpp15
4 files changed, 132 insertions, 85 deletions
diff --git a/ChangeLog b/ChangeLog
index 9bbaef6..06c830c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,8 @@
User johns
Data:
+ Add support for ac3 audio pass through.
+ Add workaround for alsa not playing hdmi sound.
Fix bug: broken device plugin stop and exit.
Show transparent cursor to hide cursor.
VDPAU: Add color standard support.
diff --git a/README.txt b/README.txt
index f50bc17..d15f70e 100644
--- a/README.txt
+++ b/README.txt
@@ -115,6 +115,10 @@ Setup: /etc/vdr/setup.conf
softhddevice.AudioDelay = 0
+n or -n ms
+ softhddevice.AudioPassthrough = 0
+ 0 = none, 1 = AC-3
+
+
Commandline:
------------
diff --git a/codec.c b/codec.c
index 58e73ff..790f2e0 100644
--- a/codec.c
+++ b/codec.c
@@ -35,8 +35,12 @@
*/
#define USE_AVPARSER
+ /// compile with passthrough support (experimental)
+#define USE_PASSTHROUGH
+
#include <stdio.h>
#include <unistd.h>
+#include <endian.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -585,8 +589,17 @@ struct _audio_decoder_
int HwChannels; ///< hw channels
ReSampleContext *ReSample; ///< audio resampling context
+
};
+#ifdef USE_PASSTHROUGH
+//static char CodecPassthroughPCM; ///< pass pcm through (unsupported)
+static char CodecPassthroughAC3; ///< pass ac3 through
+
+//static char CodecPassthroughDTS; ///< pass dts through (unsupported)
+//static char CodecPassthroughMPA; ///< pass mpa through (unsupported)
+#endif
+
/**
** Allocate a new audio decoder context.
**
@@ -683,6 +696,18 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
}
}
+/**
+** Set audio pass-through.
+*/
+void CodecSetAudioPassthrough(int mask)
+{
+#ifdef USE_PASSTHROUGH
+ CodecPassthroughAC3 = mask & 1 ? 1 : 0;
+#endif
+ // FIXME: must update audio decoder (nr. of channels wrong)
+ (void)mask;
+}
+
#ifdef USE_AVPARSER
/**
@@ -730,6 +755,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
!index ? (uint64_t) spkt->pts : AV_NOPTS_VALUE,
!index ? (uint64_t) spkt->dts : AV_NOPTS_VALUE, -1);
+ // FIXME: make this a function for both #ifdef cases
if (dpkt->size) {
int buf_sz;
@@ -765,7 +791,15 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
audio_decoder->SampleRate = audio_ctx->sample_rate;
audio_decoder->HwSampleRate = audio_ctx->sample_rate;
audio_decoder->Channels = audio_ctx->channels;
- audio_decoder->HwChannels = audio_ctx->channels;
+#ifdef USE_PASSTHROUGH
+ // SPDIF/HDMI passthrough
+ if (CodecPassthroughAC3 && audio_ctx->codec_id == CODEC_ID_AC3) {
+ audio_decoder->HwChannels = 2;
+ } else
+#endif
+ {
+ audio_decoder->HwChannels = audio_ctx->channels;
+ }
// channels not support?
if ((err =
@@ -826,6 +860,81 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
AudioEnqueue(outbuf, outlen);
}
} else {
+#ifdef USE_PASSTHROUGH
+ // SPDIF/HDMI passthrough
+ if (CodecPassthroughAC3
+ && audio_ctx->codec_id == CODEC_ID_AC3) {
+ // build SPDIF header and append A52 audio to it
+ // dpkt is the original data
+ buf_sz = 6144;
+ if (buf_sz < dpkt->size + 8) {
+ Error(_
+ ("codec/audio: decoded data smaller than encoded\n"));
+ break;
+ }
+ // copy original data for output
+ // FIXME: not 100% sure, if endian is correct
+ buf[0] = htole16(0xF872); // iec 61937 sync word
+ buf[1] = htole16(0x4E1F);
+ buf[2] = htole16(0x01 | (dpkt->data[5] & 0x07) << 8);
+ buf[3] = htole16(dpkt->size * 8);
+ swab(dpkt->data, buf + 4, dpkt->size);
+ memset(buf + 4 + dpkt->size / 2, 0,
+ buf_sz - 8 - dpkt->size);
+ }
+#if 0
+ //
+ // old experimental code
+ //
+ if (1) {
+ // FIXME: need to detect dts
+ // copy original data for output
+ // FIXME: buf is sint
+ buf[0] = 0x72;
+ buf[1] = 0xF8;
+ buf[2] = 0x1F;
+ buf[3] = 0x4E;
+ buf[4] = 0x00;
+ switch (dpkt->size) {
+ case 512:
+ buf[5] = 0x0B;
+ break;
+ case 1024:
+ buf[5] = 0x0C;
+ break;
+ case 2048:
+ buf[5] = 0x0D;
+ break;
+ default:
+ Debug(3,
+ "codec/audio: dts sample burst not supported\n");
+ buf[5] = 0x00;
+ break;
+ }
+ buf[6] = (dpkt->size * 8);
+ buf[7] = (dpkt->size * 8) >> 8;
+ //buf[8] = 0x0B;
+ //buf[9] = 0x77;
+ //printf("%x %x\n", dpkt->data[0],dpkt->data[1]);
+ // swab?
+ memcpy(buf + 8, dpkt->data, dpkt->size);
+ memset(buf + 8 + dpkt->size, 0,
+ buf_sz - 8 - dpkt->size);
+ } else if (1) {
+ // FIXME: need to detect mp2
+ // FIXME: mp2 passthrough
+ // see softhddev.c version/layer
+ // 0x04 mpeg1 layer1
+ // 0x05 mpeg1 layer23
+ // 0x06 mpeg2 ext
+ // 0x07 mpeg2.5 layer 1
+ // 0x08 mpeg2.5 layer 2
+ // 0x09 mpeg2.5 layer 3
+ }
+ // DTS HD?
+ // True HD?
+#endif
+#endif
AudioEnqueue(buf, buf_sz);
}
}
@@ -904,90 +1013,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
avcodec_decode_audio4(audio_ctx, frame, &got_frame, dpkt);
#else
#endif
- if (buf_sz > 0) { // something decoded
- // Update audio clock
- if ((uint64_t) spkt->pts != AV_NOPTS_VALUE) {
- AudioSetClock(spkt->pts);
- spkt->pts = AV_NOPTS_VALUE;
- }
- // FIXME: must first play remainings bytes, than change and play new.
- if (audio_decoder->SampleRate != audio_ctx->sample_rate
- || audio_decoder->Channels != audio_ctx->channels) {
- int err;
-
- if (audio_decoder->ReSample) {
- audio_resample_close(audio_decoder->ReSample);
- audio_decoder->ReSample = NULL;
- }
-
- audio_decoder->SampleRate = audio_ctx->sample_rate;
- audio_decoder->HwSampleRate = audio_ctx->sample_rate;
- audio_decoder->Channels = audio_ctx->channels;
- audio_decoder->HwChannels = audio_ctx->channels;
-
- // channels not support?
- if ((err =
- AudioSetup(&audio_decoder->HwSampleRate,
- &audio_decoder->HwChannels))) {
- Debug(3, "codec/audio: resample %dHz *%d -> %dHz *%d\n",
- audio_ctx->sample_rate, audio_ctx->channels,
- audio_decoder->HwSampleRate,
- audio_decoder->HwChannels);
-
- if (err == 1) {
- audio_decoder->ReSample =
- av_audio_resample_init(audio_decoder->HwChannels,
- audio_ctx->channels, audio_decoder->HwSampleRate,
- audio_ctx->sample_rate, audio_ctx->sample_fmt,
- audio_ctx->sample_fmt, 16, 10, 0, 0.8);
- // libav-0.8_pre didn't support 6 -> 2 channels
- if (!audio_decoder->ReSample) {
- Error(_("codec/audio: resample setup error\n"));
- audio_decoder->HwChannels = 0;
- audio_decoder->HwSampleRate = 0;
- }
- } else {
- // FIXME: handle errors
- Debug(3, "codec/audio: audio setup error\n");
- audio_decoder->HwChannels = 0;
- audio_decoder->HwSampleRate = 0;
- break;
- }
- }
- }
-
- if (audio_decoder->HwSampleRate && audio_decoder->HwChannels) {
- // need to resample audio
- if (audio_decoder->ReSample) {
- int16_t outbuf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 +
- FF_INPUT_BUFFER_PADDING_SIZE]
- __attribute__ ((aligned(16)));
- int outlen;
-
- // FIXME: libav-0.7.2 crash here
- outlen =
- audio_resample(audio_decoder->ReSample, outbuf, buf,
- buf_sz);
-#ifdef DEBUG
- if (outlen != buf_sz) {
- Debug(3, "codec/audio: possible fixed ffmpeg\n");
- }
-#endif
- if (outlen) {
- // outlen seems to be wrong in ffmpeg-0.9
- outlen /= audio_ctx->channels *
- av_get_bytes_per_sample(audio_ctx->sample_fmt);
- outlen *=
- audio_decoder->HwChannels *
- av_get_bytes_per_sample(audio_ctx->sample_fmt);
- Debug(4, "codec/audio: %d -> %d\n", buf_sz, outlen);
- AudioEnqueue(outbuf, outlen);
- }
- } else {
- AudioEnqueue(buf, buf_sz);
- }
- }
- }
+ // FIXME: see above, old code removed
index += n;
}
diff --git a/softhddevice.cpp b/softhddevice.cpp
index b87b422..ec65bf2 100644
--- a/softhddevice.cpp
+++ b/softhddevice.cpp
@@ -37,6 +37,7 @@ extern "C"
{
#include "video.h"
extern void AudioPoller(void);
+ extern void CodecSetAudioPassthrough(int);
}
//////////////////////////////////////////////////////////////////////////////
@@ -57,6 +58,7 @@ static int ConfigVideoDenoise; ///< config denoise
static int ConfigVideoSharpen; ///< config sharpen
static char ConfigVideoScaling; ///< config scaling
static int ConfigVideoAudioDelay; ///< config audio delay
+static int ConfigAudioPassthrough; ///< config audio pass-through
static volatile char DoMakePrimary; ///< flag switch primary
//////////////////////////////////////////////////////////////////////////////
@@ -273,6 +275,7 @@ class cMenuSetupSoft:public cMenuSetupPage
int Sharpen;
int Scaling;
int AudioDelay;
+ int AudioPassthrough;
protected:
virtual void Store(void);
public:
@@ -290,6 +293,9 @@ cMenuSetupSoft::cMenuSetupSoft(void)
static const char *const scaling[] = {
"Normal", "Fast", "HQ", "Anamorphic"
};
+ static const char *const passthrough[] = {
+ "None", "AC-3"
+ };
// cMenuEditBoolItem cMenuEditBitItem cMenuEditNumItem
// cMenuEditStrItem cMenuEditStraItem cMenuEditIntItem
@@ -313,6 +319,9 @@ cMenuSetupSoft::cMenuSetupSoft(void)
AudioDelay = ConfigVideoAudioDelay;
Add(new cMenuEditIntItem(tr("Audio delay (ms)"), &AudioDelay, -1000,
1000));
+ AudioPassthrough = ConfigAudioPassthrough;
+ Add(new cMenuEditStraItem(tr("Audio pass-through"), &AudioPassthrough, 2,
+ passthrough));
}
/**
@@ -334,6 +343,8 @@ void cMenuSetupSoft::Store(void)
VideoSetScaling(ConfigVideoScaling);
SetupStore("AudioDelay", ConfigVideoAudioDelay = AudioDelay);
VideoSetAudioDelay(ConfigVideoAudioDelay);
+ SetupStore("AudioPassthrough", ConfigAudioPassthrough = AudioPassthrough);
+ CodecSetAudioPassthrough(ConfigAudioPassthrough);
}
//////////////////////////////////////////////////////////////////////////////
@@ -837,6 +848,10 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value));
return true;
}
+ if (!strcmp(name, "AudioPassthrough")) {
+ CodecSetAudioPassthrough(ConfigAudioPassthrough = atoi(value));
+ return true;
+ }
return false;
}