rendered paste bodyIndex: xbmc/cores/dvdplayer/Codecs/DllAvCodec.h
===================================================================
--- xbmc/cores/dvdplayer/Codecs/DllAvCodec.h (revision 27554)
+++ xbmc/cores/dvdplayer/Codecs/DllAvCodec.h (working copy)
@@ -23,12 +23,14 @@
#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 @@
#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
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/Makefile.in
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/Makefile.in (revision 27554)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/Makefile.in (working copy)
@@ -13,6 +13,7 @@
DVDAudioCodecPassthrough.cpp \
DVDAudioCodecPassthroughFFmpeg.cpp \
DVDAudioCodecPcm.cpp \
+ Encoders/DVDAudioEncoderAC3.cpp
LIB=Audio.a
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp (revision 27554)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp (working copy)
@@ -33,13 +33,15 @@
/* Lookup tables */
static const uint16_t AC3Bitrates[] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640};
-static const uint16_t AC3FSCod [] = {48000, 41000, 32000, 0};
+static const uint16_t AC3FSCod [] = {48000, 44100, 32000, 0};
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,141 +54,177 @@
Dispose();
}
+bool CDVDAudioCodecPassthroughFFmpeg::SetupEncoder(CDVDStreamInfo &hints)
+{
+ /* 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;
+
+ CLog::Log(LOGDEBUG, "CDVDAudioCodecPassthroughFFmpeg::SetupEncoder - Setting up encoder for on the fly transcode");
+
+ /* 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)
+ {
+ CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::SetupEncoder - Unable to create a decoder for transcode");
+ 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()))
+ {
+ CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::SetupEncoder - Unable to create a encoder for transcode");
+ 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;
+
+ CLog::Log(LOGDEBUG, "CDVDAudioCodecPassthroughFFmpeg::SetupEncoder - Ready to transcode");
+ return true;
+}
+
bool CDVDAudioCodecPassthroughFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
{
- bool bSupportsAC3Out = false;
- bool bSupportsDTSOut = false;
- bool bSupportsAACOut = false;
- bool bSupportsMP1Out = false;
- bool bSupportsMP2Out = false;
- bool bSupportsMP3Out = false;
-
// 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))
+ // TODO - this is only valid for video files, and should be moved somewhere else
+ if( hints.channels == 2 && g_settings.m_currentVideoSettings.m_OutputToAllSpeakers )
{
+ CLog::Log(LOGINFO, "CDVDAudioCodecPassthroughFFmpeg::Open - disabled passthrough due to video OTAS");
+ return false;
+ }
- // TODO - this is only valid for video files, and should be moved somewhere else
- if( hints.channels == 2 && g_settings.m_currentVideoSettings.m_OutputToAllSpeakers )
- {
- CLog::Log(LOGINFO, "CDVDAudioCodecPassthroughFFmpeg::Open - disabled passthrough due to video OTAS");
+ /* see if the muxer supports our codec (see spdif.c for supported formats) */
+ m_pSyncFrame = NULL;
+ bool setupEncoder = true;
+ while(true) {
+ if (m_bSupportsAC3Out && hints.codec == CODEC_ID_AC3) m_pSyncFrame = &CDVDAudioCodecPassthroughFFmpeg::SyncAC3;
+ else if (m_bSupportsDTSOut && hints.codec == CODEC_ID_DTS) m_pSyncFrame = &CDVDAudioCodecPassthroughFFmpeg::SyncDTS;
+ else if (m_bSupportsAACOut && hints.codec == CODEC_ID_AAC);
+ else if (m_bSupportsMP1Out && hints.codec == CODEC_ID_MP1);
+ else if (m_bSupportsMP2Out && hints.codec == CODEC_ID_MP2);
+ else if (m_bSupportsMP3Out && hints.codec == CODEC_ID_MP3);
+ else {
+ if (setupEncoder && SetupEncoder(hints))
+ {
+ setupEncoder = false;
+ continue;
+ }
+ CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - FFmpeg SPDIF muxer does not support this codec");
+ Dispose();
return false;
}
- if (!m_dllAvFormat.Load() || !m_dllAvUtil.Load() || !m_dllAvCodec.Load())
- return false;
+ break;
+ }
- /* get the muxer */
- AVOutputFormat *outFormat;
+ if (!m_dllAvFormat.Load() || !m_dllAvUtil.Load() || !m_dllAvCodec.Load())
+ return false;
+
+ /* get the muxer */
+ AVOutputFormat *outFormat;
#if LIBAVFORMAT_VERSION_MAJOR < 53
- outFormat = m_dllAvFormat.guess_format("spdif", NULL, NULL);
+ outFormat = m_dllAvFormat.guess_format("spdif", NULL, NULL);
#else
- outFormat = m_dllAvFormat.av_guess_format("spdif", NULL, NULL);
+ outFormat = m_dllAvFormat.av_guess_format("spdif", NULL, NULL);
#endif
- if (!outFormat)
- {
- CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - Failed to get the ffmpeg spdif muxer");
- Dispose();
- return false;
- }
+ if (!outFormat)
+ {
+ CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - Failed to get the ffmpeg spdif muxer");
+ Dispose();
+ return false;
+ }
- /* 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;
+ /* allocate a the format context */
+ m_pFormat = m_dllAvFormat.avformat_alloc_context();
+ if (!m_pFormat)
+ {
+ CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - Failed to allocate AVFormat context");
+ Dispose();
+ return false;
+ }
+ m_pFormat->oformat = outFormat;
- default:
- CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - ffmpeg SPDIF muxer does not support this codec");
- Dispose();
- return false;
- }
+ /* allocate a put_byte struct so we can grab the output */
+ m_pFormat->pb = m_dllAvFormat.av_alloc_put_byte(m_bcBuffer, AVCODEC_MAX_AUDIO_FRAME_SIZE, URL_RDONLY, this, NULL, _BCReadPacket, NULL);
+ if (!m_pFormat->pb)
+ {
+ CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - Failed to allocate ByteIOContext");
+ Dispose();
+ return false;
+ }
- /* allocate a the format context */
- m_pFormat = m_dllAvFormat.avformat_alloc_context();
- if (!m_pFormat)
- {
- CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - Failed to allocate AVFormat context");
- Dispose();
- return false;
- }
- m_pFormat->oformat = outFormat;
+ /* this is streamed, no file, and ignore the index */
+ m_pFormat->pb->is_streamed = 1;
+ m_pFormat->flags |= AVFMT_NOFILE | AVFMT_FLAG_IGNIDX;
+ m_pFormat->bit_rate = hints.bitrate;
- /* allocate a put_byte struct so we can grab the output */
- m_pFormat->pb = m_dllAvFormat.av_alloc_put_byte(m_bcBuffer, AVCODEC_MAX_AUDIO_FRAME_SIZE, URL_RDONLY, this, NULL, _BCReadPacket, NULL);
- if (!m_pFormat->pb)
- {
- CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - Failed to allocate ByteIOContext");
- Dispose();
- return false;
- }
+ /* setup the muxer */
+ AVFormatParameters params;
+ memset(¶ms, 0, sizeof(params));
+ params.channels = hints.channels;
+ params.sample_rate = OUT_SAMPLERATE;
+ params.channel = 0;
+ if (m_dllAvFormat.av_set_parameters(m_pFormat, ¶ms) != 0)
+ {
+ CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - Failed to set the spdif muxer parameters");
+ Dispose();
+ return false;
+ }
- /* this is streamed, no file, and ignore the index */
- m_pFormat->pb->is_streamed = 1;
- m_pFormat->flags |= AVFMT_NOFILE | AVFMT_FLAG_IGNIDX;
- m_pFormat->bit_rate = hints.bitrate;
+ /* add a stream to it */
+ m_pStream = m_dllAvFormat.av_new_stream(m_pFormat, 1);
+ if (!m_pStream)
+ {
+ CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - Failed to allocate AVStream context");
+ Dispose();
+ return false;
+ }
- /* setup the muxer */
- AVFormatParameters params;
- memset(¶ms, 0, sizeof(params));
- params.channels = hints.channels;
- params.sample_rate = OUT_SAMPLERATE;
- params.channel = 0;
- if (m_dllAvFormat.av_set_parameters(m_pFormat, ¶ms) != 0)
- {
- CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - Failed to set the spdif muxer parameters");
- Dispose();
- return false;
- }
+ /* set the stream's parameters */
+ m_pStream->stream_copy = 1;
+ m_pStream->codec->codec_type = CODEC_TYPE_AUDIO;
+ m_pStream->codec->codec_id = hints.codec;
+ m_pStream->codec->sample_rate = hints.samplerate;
+ m_pStream->codec->channels = hints.channels;
- /* add a stream to it */
- m_pStream = m_dllAvFormat.av_new_stream(m_pFormat, 1);
- if (!m_pStream)
- {
- CLog::Log(LOGERROR, "CDVDAudioCodecPassthroughFFmpeg::Open - Failed to allocate AVStream context");
- Dispose();
- return false;
- }
+ /* we will check the first packet's crc */
+ m_lostSync = true;
+ return true;
+}
- /* set the stream's parameters */
- m_pStream->stream_copy = 1;
- m_pStream->codec->codec_type = CODEC_TYPE_AUDIO;
- m_pStream->codec->codec_id = hints.codec;
- m_pStream->codec->sample_rate = hints.samplerate;
- m_pStream->codec->channels = hints.channels;
+void CDVDAudioCodecPassthroughFFmpeg::Dispose()
+{
+ if (m_encoder)
+ {
+ delete m_encoder;
+ m_encoder = NULL;
+ }
- /* we will check the first packet's crc */
- m_lostSync = true;
- return true;
+ if (m_codec)
+ {
+ delete m_codec;
+ m_codec = NULL;
}
- return false;
-}
-
-void CDVDAudioCodecPassthroughFFmpeg::Dispose()
-{
- if (m_pFormat) {
+ if (m_pFormat)
+ {
if (m_pFormat->pb)
m_dllAvUtil.av_freep(&m_pFormat->pb);
m_dllAvUtil.av_freep(&m_pFormat);
@@ -218,7 +256,6 @@
/* search for an ac3 sync word */
if(pData[0] != 0x0b || pData[1] != 0x77)
continue;
-
uint8_t fscod = pData[4] >> 6;
uint8_t frmsizecod = pData[4] & 0x3F;
uint8_t bsid = pData[5] >> 3;
@@ -280,11 +317,11 @@
) 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,14 +335,36 @@
int CDVDAudioCodecPassthroughFFmpeg::Decode(BYTE* pData, int iSize)
{
- int fSize = iSize;
- if (m_pSyncFrame)
+ int used, fSize;
+ used = fSize = iSize;
+
+ /* if we are transcoding */
+ if (m_encoder)
{
- int skip = (this->*m_pSyncFrame)(pData, iSize, &fSize);
- if (skip > 0)
- return skip;
+ BYTE *decData;
+ BYTE encData[6114];
+ used = m_codec ->Decode (pData, iSize);
+ fSize = m_codec ->GetData(&decData);
+ fSize = m_encoder->Encode (decData, fSize);
+ fSize = m_encoder->GetData(encData, 6114);
+ pData = encData;
+
+ /* if the encoder has not got anything yet, return the consumed bytes */
+ if (fSize == 0)
+ return used;
}
+ else
+ {
+ if (m_pSyncFrame)
+ {
+ int skip = (this->*m_pSyncFrame)(pData, iSize, &fSize);
+ if (skip > 0)
+ return skip;
+ used = fSize;
+ }
+ }
+
AVPacket pkt;
m_dllAvCodec.av_init_packet(&pkt);
pkt.data = pData;
@@ -314,7 +373,8 @@
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)
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.h (revision 27554)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.h (working copy)
@@ -25,7 +25,10 @@
#include "Codecs/DllAvFormat.h"
#include "Codecs/DllAvCodec.h"
+#include "../DVDFactoryCodec.h"
#include "DVDAudioCodec.h"
+#include "Encoders/IDVDAudioEncoder.h"
+#include "Encoders/DVDAudioEncoderAC3.h"
class CDVDAudioCodecPassthroughFFmpeg : public CDVDAudioCodec
{
@@ -46,6 +49,17 @@
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);
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/DVDAudioEncoderAC3.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/DVDAudioEncoderAC3.cpp (revision 0)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/DVDAudioEncoderAC3.cpp (revision 0)
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2005-2010 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "DVDAudioEncoderAC3.h"
+#include <string.h>
+
+CDVDAudioEncoderAC3::CDVDAudioEncoderAC3():
+ m_codecCtx (NULL)
+{
+}
+
+CDVDAudioEncoderAC3::~CDVDAudioEncoderAC3()
+{
+ Reset();
+}
+
+bool CDVDAudioEncoderAC3::Initialize(unsigned int channels, enum PCMChannels *channelMap, unsigned int bitsPerSample, unsigned int sampleRate)
+{
+ Reset();
+ if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load())
+ return false;
+
+ AVCodec *codec;
+ codec = m_dllAvCodec.avcodec_find_encoder(CODEC_ID_AC3);
+ if (!codec)
+ return false;
+
+ /* always assume 6 channels, 5.1... m_remap will give us what we want */
+ m_codecCtx = m_dllAvCodec.avcodec_alloc_context();
+ m_codecCtx->bit_rate = 448000;
+ m_codecCtx->sample_rate = sampleRate;
+ m_codecCtx->channels = 6;
+ m_codecCtx->channel_layout = CH_LAYOUT_5POINT1;
+
+ switch(bitsPerSample)
+ {
+ case 8: m_codecCtx->sample_fmt = SAMPLE_FMT_U8 ; break;
+ case 16: m_codecCtx->sample_fmt = SAMPLE_FMT_S16; break;
+ case 32: m_codecCtx->sample_fmt = SAMPLE_FMT_S32; break;
+ default:
+ m_dllAvUtil.av_freep(&m_codecCtx);
+ return false;
+ }
+
+ if (m_dllAvCodec.avcodec_open(m_codecCtx, codec))
+ {
+ m_dllAvUtil.av_freep(&m_codecCtx);
+ return false;
+ }
+
+ /* remap the channels according to the specified channel layout */
+ int index = 0;
+ if (m_codecCtx->channel_layout && CH_FRONT_LEFT ) m_channelMap[index++] = PCM_FRONT_LEFT ;
+ if (m_codecCtx->channel_layout && CH_FRONT_RIGHT ) m_channelMap[index++] = PCM_FRONT_RIGHT ;
+ if (m_codecCtx->channel_layout && CH_FRONT_CENTER ) m_channelMap[index++] = PCM_FRONT_CENTER ;
+ if (m_codecCtx->channel_layout && CH_LOW_FREQUENCY ) m_channelMap[index++] = PCM_LOW_FREQUENCY ;
+ if (m_codecCtx->channel_layout && CH_BACK_LEFT ) m_channelMap[index++] = PCM_BACK_LEFT ;
+ if (m_codecCtx->channel_layout && CH_BACK_RIGHT ) m_channelMap[index++] = PCM_BACK_RIGHT ;
+ if (m_codecCtx->channel_layout && CH_FRONT_LEFT_OF_CENTER ) m_channelMap[index++] = PCM_FRONT_LEFT_OF_CENTER ;
+ if (m_codecCtx->channel_layout && CH_FRONT_RIGHT_OF_CENTER) m_channelMap[index++] = PCM_FRONT_RIGHT_OF_CENTER;
+ if (m_codecCtx->channel_layout && CH_BACK_CENTER ) m_channelMap[index++] = PCM_BACK_CENTER ;
+ if (m_codecCtx->channel_layout && CH_SIDE_LEFT ) m_channelMap[index++] = PCM_SIDE_LEFT ;
+ if (m_codecCtx->channel_layout && CH_SIDE_RIGHT ) m_channelMap[index++] = PCM_SIDE_RIGHT ;
+ if (m_codecCtx->channel_layout && CH_TOP_CENTER ) m_channelMap[index++] = PCM_TOP_CENTER ;
+ if (m_codecCtx->channel_layout && CH_TOP_FRONT_LEFT ) m_channelMap[index++] = PCM_TOP_FRONT_LEFT ;
+ if (m_codecCtx->channel_layout && CH_TOP_FRONT_CENTER ) m_channelMap[index++] = PCM_TOP_FRONT_CENTER ;
+ if (m_codecCtx->channel_layout && CH_TOP_FRONT_RIGHT ) m_channelMap[index++] = PCM_TOP_FRONT_RIGHT ;
+ if (m_codecCtx->channel_layout && CH_TOP_BACK_LEFT ) m_channelMap[index++] = PCM_TOP_BACK_LEFT ;
+ if (m_codecCtx->channel_layout && CH_TOP_BACK_CENTER ) m_channelMap[index++] = PCM_TOP_BACK_CENTER ;
+ if (m_codecCtx->channel_layout && CH_TOP_BACK_RIGHT ) m_channelMap[index++] = PCM_TOP_BACK_RIGHT ;
+
+ m_remap.SetInputFormat (channels, channelMap, bitsPerSample / 8);
+ m_remap.SetOutputFormat(index , m_channelMap);
+
+ if (!m_remap.CanRemap())
+ {
+ m_dllAvUtil.av_freep(&m_codecCtx);
+ return false;
+ }
+
+ return true;
+}
+
+void CDVDAudioEncoderAC3::Reset()
+{
+ while(!m_packets.empty())
+ {
+ DSPAC3PacketInfo *info;
+ info = m_packets.front();
+ m_packets.pop_front();
+ delete[] info->data;
+ delete info;
+ }
+}
+
+unsigned int CDVDAudioEncoderAC3::GetBitRate()
+{
+ return m_codecCtx->bit_rate;
+}
+
+CodecID CDVDAudioEncoderAC3::GetCodecID()
+{
+ return CODEC_ID_AC3;
+}
+
+int CDVDAudioEncoderAC3::Encode(void *data, int size)
+{
+ uint8_t *pos = (uint8_t*)data;
+ int consumed = 0;
+ int frames = m_remap.InBytesToFrames (size);
+ int outsize = m_remap.FramesToOutBytes(frames);
+ int stride = m_remap.FramesToInBytes (256);
+
+ /* remap the data and encode it in blocks of 256 frames */
+ while(frames >= 256)
+ {
+ uint8_t remapped[outsize];
+ m_remap.Remap(pos, remapped, 256);
+
+ DSPAC3PacketInfo *info;
+ info = new DSPAC3PacketInfo();
+ info->size = outsize;
+ info->data = new uint8_t[AC3_MAX_CODED_FRAME_SIZE];
+ info->pos = info->data;
+ info->size = m_dllAvCodec.avcodec_encode_audio(m_codecCtx, info->data, outsize, (short*)remapped);
+
+ consumed += stride;
+ pos += stride;
+ frames -= 256;
+
+ m_packets.push_back(info);
+ }
+
+ /* return the consumed bytes */
+ return consumed;
+}
+
+int CDVDAudioEncoderAC3::GetData(void *data, int size)
+{
+ if (m_packets.empty()) return 0;
+
+ DSPAC3PacketInfo *info = m_packets.front();
+
+ /* figure out how much data we can copy */
+ int available = info->size - (info->pos - info->data);
+ int use;
+ if (available > size)
+ use = size;
+ else
+ use = available;
+
+ /* copy it into the destination buffer */
+ memcpy(data, info->pos, use);
+ info->pos += use;
+
+ /* if this list item is empty, then remove it */
+ if (info->size - (info->pos - info->data) == 0)
+ {
+ delete[] info->data;
+ delete info;
+ m_packets.pop_front();
+ }
+
+ return use;
+}
+
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/DVDAudioEncoderAC3.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/DVDAudioEncoderAC3.h (revision 0)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/DVDAudioEncoderAC3.h (revision 0)
@@ -0,0 +1,59 @@
+#pragma once
+/*
+ * Copyright (C) 2005-2010 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <list>
+#include "IDVDAudioEncoder.h"
+#include "Codecs/DllAvCodec.h"
+#include "Codecs/DllAvFormat.h"
+
+class CDVDAudioEncoderAC3: public IDVDAudioEncoder
+{
+public:
+ CDVDAudioEncoderAC3();
+ virtual ~CDVDAudioEncoderAC3();
+ virtual bool Initialize(unsigned int channels, enum PCMChannels *channelMap, unsigned int bitsPerSample, unsigned int sampleRate);
+ virtual void Reset();
+
+ /* returns this DSPs output format */
+ virtual unsigned int GetBitRate ();
+ virtual CodecID GetCodecID ();
+
+ /* add/get packets to/from the DSP */
+ virtual int Encode (void *data, int size);
+ virtual int GetData(void *data, int size);
+private:
+ typedef struct
+ {
+ unsigned int size;
+ uint8_t *data;
+ uint8_t *pos;
+ } DSPAC3PacketInfo;
+
+ std::list<DSPAC3PacketInfo*> m_packets;
+ DllAvCodec m_dllAvCodec;
+ DllAvUtil m_dllAvUtil;
+
+ AVCodecContext *m_codecCtx;
+ enum PCMChannels m_channelMap[PCM_MAX_CH];
+ CPCMRemap m_remap;
+};
+
Index: xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/IDVDAudioEncoder.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/IDVDAudioEncoder.h (revision 0)
+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/IDVDAudioEncoder.h (revision 0)
@@ -0,0 +1,42 @@
+#pragma once
+/*
+ * Copyright (C) 2005-2010 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "utils/PCMRemap.h"
+#include "DVDStreamInfo.h"
+
+class IDVDAudioEncoder
+{
+public:
+ IDVDAudioEncoder() {};
+ virtual ~IDVDAudioEncoder() {};
+ virtual bool Initialize(unsigned int channels, enum PCMChannels *channelMap, unsigned int bitsPerSample, unsigned int sampleRate) = 0;
+ virtual void Reset() = 0;
+
+ /* returns this DSPs output format */
+ virtual unsigned int GetBitRate() = 0;
+ virtual CodecID GetCodecID() = 0;
+
+ /* add/get packets to/from the DSP */
+ virtual int Encode (void *data, int size) = 0;
+ virtual int GetData(void *data, int size) = 0;
+};
+
Index: xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp (revision 27554)
+++ xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp (working copy)
@@ -177,18 +177,21 @@
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)
{
Index: xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h
===================================================================
--- xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h (revision 27554)
+++ xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h (working copy)
@@ -36,7 +36,7 @@
{
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 );
Index: xbmc/utils/PCMRemap.h
===================================================================
--- xbmc/utils/PCMRemap.h (revision 27554)
+++ xbmc/utils/PCMRemap.h (working copy)
@@ -101,6 +101,9 @@
void SetOutputFormat(unsigned int channels, enum PCMChannels *channelMap);
void Remap(void *data, void *out, unsigned int samples);
bool CanRemap();
+ int InBytesToFrames (int bytes );
+ int FramesToOutBytes(int frames);
+ int FramesToInBytes (int frames);
};
#endif
Index: xbmc/utils/PCMRemap.cpp
===================================================================
--- xbmc/utils/PCMRemap.cpp (revision 27554)
+++ xbmc/utils/PCMRemap.cpp (working copy)
@@ -465,3 +465,18 @@
return (m_inSet && m_outSet);
}
+int CPCMRemap::InBytesToFrames(int bytes)
+{
+ return bytes / m_inSampleSize / m_inChannels;
+}
+
+int CPCMRemap::FramesToOutBytes(int frames)
+{
+ return frames * m_inSampleSize * m_outChannels;
+}
+
+int CPCMRemap::FramesToInBytes(int frames)
+{
+ return frames * m_inSampleSize * m_inChannels;
+}
+