rendered paste bodydiff --git a/xbmc/cores/dvdplayer/Codecs/DllAvCodec.h b/xbmc/cores/dvdplayer/Codecs/DllAvCodec.h
index 87b9f95..be75c52 100644
--- a/xbmc/cores/dvdplayer/Codecs/DllAvCodec.h
+++ b/xbmc/cores/dvdplayer/Codecs/DllAvCodec.h
@@ -23,12 +23,14 @@ extern "C" {
#if (defined USE_EXTERNAL_FFMPEG)
#if (defined HAVE_LIBAVCODEC_AVCODEC_H)
#include <libavcodec/avcodec.h>
+ #include <libavcodec/ac3.h>
#include <libavutil/crc.h>
#if (defined AVPACKET_IN_AVFORMAT)
#include <libavformat/avformat.h>
#endif
#elif (defined HAVE_FFMPEG_AVCODEC_H)
#include <ffmpeg/avcodec.h>
+ #include <ffmpeg/ac3.h>
#include <ffmpeg/crc.h>
#if (defined AVPACKET_IN_AVFORMAT)
#include <ffmpeg/avformat.h>
@@ -39,6 +41,7 @@ extern "C" {
#include "xbmc/cores/dvdplayer/Codecs/ffmpeg/libavutil/crc.h"
#else
#include "libavcodec/avcodec.h"
+ #include "libavcodec/ac3.h"
#include "libavcodec/audioconvert.h"
#include "libavutil/crc.h"
#endif
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp
index 96958da..f623ed0 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp
@@ -26,6 +26,10 @@
#include "Settings.h"
#include "utils/log.h"
+#include "../../DVDStreamInfo.h"
+#include "../DVDFactoryCodec.h"
+#include "Encoders/DVDAudioEncoderAC3.h"
+
//These values are forced to allow spdif out
#define OUT_SAMPLESIZE 16
#define OUT_CHANNELS 2
@@ -40,6 +44,8 @@ CDVDAudioCodecPassthroughFFmpeg::CDVDAudioCodecPassthroughFFmpeg(void)
m_pFormat = NULL;
m_pStream = NULL;
m_pSyncFrame = NULL;
+ m_codec = NULL;
+ m_encoder = NULL;
m_OutputSize = 0;
m_OutputBuffer = (BYTE*)_aligned_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE, 16);
@@ -52,34 +58,55 @@ CDVDAudioCodecPassthroughFFmpeg::~CDVDAudioCodecPassthroughFFmpeg(void)
Dispose();
}
-bool CDVDAudioCodecPassthroughFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
+bool CDVDAudioCodecPassthroughFFmpeg::SetupEncoder(CDVDStreamInfo &hints)
{
- bool bSupportsAC3Out = false;
- bool bSupportsDTSOut = false;
- bool bSupportsAACOut = false;
- bool bSupportsMP1Out = false;
- bool bSupportsMP2Out = false;
- bool bSupportsMP3Out = false;
+ /* there is no point encoding < 2 channel sources, and we dont support anything but AC3 at the moment */
+ if (hints.channels <= 2 || !m_bSupportsAC3Out)
+ return false;
+
+ /* we need to decode the incoming audio data, so we can re-encode it as we need it */
+ m_codec = CDVDFactoryCodec::CreateAudioCodec(hints, false);
+ if (!m_codec)
+ return false;
+
+ /* try to open the encoder */
+ m_encoder = new CDVDAudioEncoderAC3();
+ if (!m_encoder->Initialize(m_codec->GetChannels(), m_codec->GetChannelMap(), m_codec->GetBitsPerSample(), m_codec->GetSampleRate()))
+ {
+ Dispose();
+ return false;
+ }
+
+ /* adjust the hints according to the encorders output */
+ hints.codec = m_encoder->GetCodecID ();
+ hints.bitrate = m_encoder->GetBitRate ();
+ hints.channels = OUT_CHANNELS;
+ return true;
+}
+bool CDVDAudioCodecPassthroughFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
+{
// TODO - move this stuff somewhere else
if (g_guiSettings.GetInt("audiooutput.mode") == AUDIO_DIGITAL)
{
- bSupportsAC3Out = g_guiSettings.GetBool("audiooutput.ac3passthrough");
- bSupportsDTSOut = g_guiSettings.GetBool("audiooutput.dtspassthrough");
- bSupportsAACOut = g_guiSettings.GetBool("audiooutput.aacpassthrough");
- bSupportsMP1Out = g_guiSettings.GetBool("audiooutput.mp1passthrough");
- bSupportsMP2Out = g_guiSettings.GetBool("audiooutput.mp2passthrough");
- bSupportsMP3Out = g_guiSettings.GetBool("audiooutput.mp3passthrough");
+ m_bSupportsAC3Out = g_guiSettings.GetBool("audiooutput.ac3passthrough");
+ m_bSupportsDTSOut = g_guiSettings.GetBool("audiooutput.dtspassthrough");
+ m_bSupportsAACOut = g_guiSettings.GetBool("audiooutput.aacpassthrough");
+ m_bSupportsMP1Out = g_guiSettings.GetBool("audiooutput.mp1passthrough");
+ m_bSupportsMP2Out = g_guiSettings.GetBool("audiooutput.mp2passthrough");
+ m_bSupportsMP3Out = g_guiSettings.GetBool("audiooutput.mp3passthrough");
}
+ else
+ return false;
//Samplerate cannot be checked here as we don't know it at this point in time.
//We should probably have a way to try to decode data so that we know what samplerate it is.
- if ((hints.codec == CODEC_ID_AC3 && bSupportsAC3Out)
- || (hints.codec == CODEC_ID_DTS && bSupportsDTSOut)
- || (hints.codec == CODEC_ID_AAC && bSupportsAACOut)
- || (hints.codec == CODEC_ID_MP1 && bSupportsMP1Out)
- || (hints.codec == CODEC_ID_MP2 && bSupportsMP2Out)
- || (hints.codec == CODEC_ID_MP3 && bSupportsMP3Out))
+ if ((hints.codec == CODEC_ID_AC3 && m_bSupportsAC3Out)
+ || (hints.codec == CODEC_ID_DTS && m_bSupportsDTSOut)
+ || (hints.codec == CODEC_ID_AAC && m_bSupportsAACOut)
+ || (hints.codec == CODEC_ID_MP1 && m_bSupportsMP1Out)
+ || (hints.codec == CODEC_ID_MP2 && m_bSupportsMP2Out)
+ || (hints.codec == CODEC_ID_MP3 && m_bSupportsMP3Out))
{
// TODO - this is only valid for video files, and should be moved somewhere else
@@ -108,19 +135,28 @@ bool CDVDAudioCodecPassthroughFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptio
/* see if the muxer supports our codec (see spdif.c for supported formats) */
m_pSyncFrame = NULL;
- switch(hints.codec) {
- case CODEC_ID_AC3: m_pSyncFrame = &CDVDAudioCodecPassthroughFFmpeg::SyncAC3; break;
- case CODEC_ID_DTS: m_pSyncFrame = &CDVDAudioCodecPassthroughFFmpeg::SyncDTS; break;
- case CODEC_ID_MP1:
- case CODEC_ID_MP2:
- case CODEC_ID_MP3:
- case CODEC_ID_AAC:
- break;
-
- default:
- CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - ffmpeg SPDIF muxer does not support this codec");
- Dispose();
- return false;
+ bool setupEncoder = true;
+ while(true) {
+ switch(hints.codec) {
+ case CODEC_ID_AC3: m_pSyncFrame = &CDVDAudioCodecPassthroughFFmpeg::SyncAC3; break;
+ case CODEC_ID_DTS: m_pSyncFrame = &CDVDAudioCodecPassthroughFFmpeg::SyncDTS; break;
+ case CODEC_ID_MP1:
+ case CODEC_ID_MP2:
+ case CODEC_ID_MP3:
+ case CODEC_ID_AAC:
+ break;
+
+ default:
+ if (setupEncoder && SetupEncoder(hints))
+ {
+ setupEncoder = false;
+ continue;
+ }
+ CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - FFmpeg SPDIF muxer does not support this codec");
+ Dispose();
+ return false;
+ }
+ break;
}
/* allocate a the format context */
@@ -186,7 +222,20 @@ bool CDVDAudioCodecPassthroughFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptio
void CDVDAudioCodecPassthroughFFmpeg::Dispose()
{
- if (m_pFormat) {
+ if (m_encoder)
+ {
+ delete m_encoder;
+ m_encoder = NULL;
+ }
+
+ if (m_codec)
+ {
+ delete m_codec;
+ m_codec = NULL;
+ }
+
+ if (m_pFormat)
+ {
if (m_pFormat->pb)
m_dllAvUtil.av_freep(&m_pFormat->pb);
m_dllAvUtil.av_freep(&m_pFormat);
@@ -280,11 +329,11 @@ int CDVDAudioCodecPassthroughFFmpeg::SyncDTS(BYTE* pData, int iSize, int *fSize)
) continue;
/* if it is not a termination frame, check the next 6 bits */
- if (pData[4] & 0x80 != 0 && pData[4] & 0x7C != 0x7C)
+ if ((pData[4] & 0x80) != 0 && (pData[4] & 0x7C) != 0x7C)
continue;
/* get and validate the framesize */
- *fSize = ((pData[5] & 0x3) << 8 | pData[6]) << 4 | ((pData[7] & 0xF0) >> 4) + 1;
+ *fSize = ((((pData[5] & 0x3) << 8 | pData[6]) << 4) | ((pData[7] & 0xF0) >> 4)) + 1;
if (*fSize < 95 || *fSize > 16383)
continue;
@@ -298,12 +347,32 @@ int CDVDAudioCodecPassthroughFFmpeg::SyncDTS(BYTE* pData, int iSize, int *fSize)
int CDVDAudioCodecPassthroughFFmpeg::Decode(BYTE* pData, int iSize)
{
- int fSize = iSize;
- if (m_pSyncFrame)
+ int used, fSize;
+ used = fSize = iSize;
+
+ /* if we are encoding */
+ if (m_encoder)
{
- int skip = (this->*m_pSyncFrame)(pData, iSize, &fSize);
- if (skip > 0)
- return skip;
+ BYTE *decData;
+ BYTE encData[6144];
+ used = m_codec ->Decode (pData, iSize);
+ iSize = m_codec ->GetData(&decData);
+ iSize = m_encoder->Encode (decData, iSize);
+ fSize = m_encoder->GetData(encData, 6144);
+ pData = encData;
+
+ /* if the encoder has not got anything yet, return the consumed bytes */
+ if (iSize == 0)
+ return used;
+ }
+ else
+ {
+ if (m_pSyncFrame)
+ {
+ int skip = (this->*m_pSyncFrame)(pData, iSize, &fSize);
+ if (skip > 0)
+ return skip;
+ }
}
AVPacket pkt;
@@ -314,7 +383,8 @@ int CDVDAudioCodecPassthroughFFmpeg::Decode(BYTE* pData, int iSize)
m_dllAvFormat.av_write_header (m_pFormat);
m_dllAvFormat.av_write_frame (m_pFormat, &pkt);
m_dllAvFormat.av_write_trailer(m_pFormat);
- return fSize;
+
+ return used;
}
int CDVDAudioCodecPassthroughFFmpeg::GetData(BYTE** dst)
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.h
index 1971c56..25d6f50 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.h
@@ -26,6 +26,7 @@
#include "Codecs/DllAvCodec.h"
#include "DVDAudioCodec.h"
+#include "Encoders/IDVDAudioEncoder.h"
class CDVDAudioCodecPassthroughFFmpeg : public CDVDAudioCodec
{
@@ -46,6 +47,17 @@ public:
virtual const char* GetName() { return "PassthroughFFmpeg"; }
private:
+ bool m_bSupportsAC3Out;
+ bool m_bSupportsDTSOut;
+ bool m_bSupportsAACOut;
+ bool m_bSupportsMP1Out;
+ bool m_bSupportsMP2Out;
+ bool m_bSupportsMP3Out;
+
+ CDVDAudioCodec *m_codec ;
+ IDVDAudioEncoder *m_encoder;
+ bool SetupEncoder(CDVDStreamInfo &hints);
+
int (CDVDAudioCodecPassthroughFFmpeg::*m_pSyncFrame)(BYTE* pData, int iSize, int *fSize);
int SyncAC3(BYTE* pData, int iSize, int *fSize);
int SyncDTS(BYTE* pData, int iSize, int *fSize);
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Audio/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Audio/Makefile.in
index 303fd2c..33410b9 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/Audio/Makefile.in
+++ b/xbmc/cores/dvdplayer/DVDCodecs/Audio/Makefile.in
@@ -13,6 +13,7 @@ SRCS= DVDAudioCodecFFmpeg.cpp \
DVDAudioCodecPassthrough.cpp \
DVDAudioCodecPassthroughFFmpeg.cpp \
DVDAudioCodecPcm.cpp \
+ Encoders/DVDAudioEncoderAC3.cpp
LIB=Audio.a
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
index 2530221..f802616 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
+++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
@@ -177,18 +177,21 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec( CDVDStreamInfo &hint )
return NULL;
}
-CDVDAudioCodec* CDVDFactoryCodec::CreateAudioCodec( CDVDStreamInfo &hint )
+CDVDAudioCodec* CDVDFactoryCodec::CreateAudioCodec( CDVDStreamInfo &hint, bool passthrough /* = true */)
{
CDVDAudioCodec* pCodec = NULL;
CDVDCodecOptions options;
+ if (passthrough)
+ {
#if defined(USE_LIBA52_DECODER) || defined(USE_LIBDTS_DECODER)
- pCodec = OpenCodec( new CDVDAudioCodecPassthrough(), hint, options );
- if( pCodec ) return pCodec;
+ pCodec = OpenCodec( new CDVDAudioCodecPassthrough(), hint, options );
+ if( pCodec ) return pCodec;
#endif
- pCodec = OpenCodec( new CDVDAudioCodecPassthroughFFmpeg(), hint, options);
- if ( pCodec ) return pCodec;
+ pCodec = OpenCodec( new CDVDAudioCodecPassthroughFFmpeg(), hint, options);
+ if ( pCodec ) return pCodec;
+ }
switch (hint.codec)
{
diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h
index 09885b0..317100e 100644
--- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h
+++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h
@@ -36,7 +36,7 @@ class CDVDFactoryCodec
{
public:
static CDVDVideoCodec* CreateVideoCodec(CDVDStreamInfo &hint );
- static CDVDAudioCodec* CreateAudioCodec(CDVDStreamInfo &hint );
+ static CDVDAudioCodec* CreateAudioCodec(CDVDStreamInfo &hint, bool passthrough = true );
static CDVDOverlayCodec* CreateOverlayCodec(CDVDStreamInfo &hint );
static CDVDAudioCodec* OpenCodec(CDVDAudioCodec* pCodec, CDVDStreamInfo &hint, CDVDCodecOptions &options );