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" #endifIndex: 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,178 @@ Dispose(); } +bool CDVDAudioCodecPassthroughFFmpeg::SupportsFormat(CDVDStreamInfo &hints)+{+ m_pSyncFrame = NULL;++ 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 return false;++ return true;+}++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 )+ /* see if the muxer supports our codec (see spdif.c for supported formats) */+ bool setupEncoder = true;+ if (!SupportsFormat(hints))+ if (!SetupEncoder(hints) || !SupportsFormat(hints)) {- CLog::Log(LOGINFO, "CDVDAudioCodecPassthroughFFmpeg::Open - disabled passthrough due to video OTAS");+ 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;+ if (!m_dllAvFormat.Load() || !m_dllAvUtil.Load() || !m_dllAvCodec.Load())+ return false; - /* get the muxer */- AVOutputFormat *outFormat;+ /* 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 +257,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 +318,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 +336,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 +374,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,18 @@ 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 SupportsFormat(CDVDStreamInfo &hints);+ 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/Audio/DVDAudioCodecFFmpeg.cpp===================================================================--- xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp (revision 27554)+++ xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecFFmpeg.cpp (working copy)@@ -256,24 +256,24 @@ void CDVDAudioCodecFFmpeg::BuildChannelMap() { int index = 0;- if (m_pCodecContext->channel_layout && CH_FRONT_LEFT ) m_channelMap[index++] = PCM_FRONT_LEFT ;- if (m_pCodecContext->channel_layout && CH_FRONT_RIGHT ) m_channelMap[index++] = PCM_FRONT_RIGHT ;- if (m_pCodecContext->channel_layout && CH_FRONT_CENTER ) m_channelMap[index++] = PCM_FRONT_CENTER ;- if (m_pCodecContext->channel_layout && CH_LOW_FREQUENCY ) m_channelMap[index++] = PCM_LOW_FREQUENCY ;- if (m_pCodecContext->channel_layout && CH_BACK_LEFT ) m_channelMap[index++] = PCM_BACK_LEFT ;- if (m_pCodecContext->channel_layout && CH_BACK_RIGHT ) m_channelMap[index++] = PCM_BACK_RIGHT ;- if (m_pCodecContext->channel_layout && CH_FRONT_LEFT_OF_CENTER ) m_channelMap[index++] = PCM_FRONT_LEFT_OF_CENTER ;- if (m_pCodecContext->channel_layout && CH_FRONT_RIGHT_OF_CENTER) m_channelMap[index++] = PCM_FRONT_RIGHT_OF_CENTER;- if (m_pCodecContext->channel_layout && CH_BACK_CENTER ) m_channelMap[index++] = PCM_BACK_CENTER ;- if (m_pCodecContext->channel_layout && CH_SIDE_LEFT ) m_channelMap[index++] = PCM_SIDE_LEFT ;- if (m_pCodecContext->channel_layout && CH_SIDE_RIGHT ) m_channelMap[index++] = PCM_SIDE_RIGHT ;- if (m_pCodecContext->channel_layout && CH_TOP_CENTER ) m_channelMap[index++] = PCM_TOP_CENTER ;- if (m_pCodecContext->channel_layout && CH_TOP_FRONT_LEFT ) m_channelMap[index++] = PCM_TOP_FRONT_LEFT ;- if (m_pCodecContext->channel_layout && CH_TOP_FRONT_CENTER ) m_channelMap[index++] = PCM_TOP_FRONT_CENTER ;- if (m_pCodecContext->channel_layout && CH_TOP_FRONT_RIGHT ) m_channelMap[index++] = PCM_TOP_FRONT_RIGHT ;- if (m_pCodecContext->channel_layout && CH_TOP_BACK_LEFT ) m_channelMap[index++] = PCM_TOP_BACK_LEFT ;- if (m_pCodecContext->channel_layout && CH_TOP_BACK_CENTER ) m_channelMap[index++] = PCM_TOP_BACK_CENTER ;- if (m_pCodecContext->channel_layout && CH_TOP_BACK_RIGHT ) m_channelMap[index++] = PCM_TOP_BACK_RIGHT ;+ if (m_pCodecContext->channel_layout & CH_FRONT_LEFT ) m_channelMap[index++] = PCM_FRONT_LEFT ;+ if (m_pCodecContext->channel_layout & CH_FRONT_RIGHT ) m_channelMap[index++] = PCM_FRONT_RIGHT ;+ if (m_pCodecContext->channel_layout & CH_FRONT_CENTER ) m_channelMap[index++] = PCM_FRONT_CENTER ;+ if (m_pCodecContext->channel_layout & CH_LOW_FREQUENCY ) m_channelMap[index++] = PCM_LOW_FREQUENCY ;+ if (m_pCodecContext->channel_layout & CH_BACK_LEFT ) m_channelMap[index++] = PCM_BACK_LEFT ;+ if (m_pCodecContext->channel_layout & CH_BACK_RIGHT ) m_channelMap[index++] = PCM_BACK_RIGHT ;+ if (m_pCodecContext->channel_layout & CH_FRONT_LEFT_OF_CENTER ) m_channelMap[index++] = PCM_FRONT_LEFT_OF_CENTER ;+ if (m_pCodecContext->channel_layout & CH_FRONT_RIGHT_OF_CENTER) m_channelMap[index++] = PCM_FRONT_RIGHT_OF_CENTER;+ if (m_pCodecContext->channel_layout & CH_BACK_CENTER ) m_channelMap[index++] = PCM_BACK_CENTER ;+ if (m_pCodecContext->channel_layout & CH_SIDE_LEFT ) m_channelMap[index++] = PCM_SIDE_LEFT ;+ if (m_pCodecContext->channel_layout & CH_SIDE_RIGHT ) m_channelMap[index++] = PCM_SIDE_RIGHT ;+ if (m_pCodecContext->channel_layout & CH_TOP_CENTER ) m_channelMap[index++] = PCM_TOP_CENTER ;+ if (m_pCodecContext->channel_layout & CH_TOP_FRONT_LEFT ) m_channelMap[index++] = PCM_TOP_FRONT_LEFT ;+ if (m_pCodecContext->channel_layout & CH_TOP_FRONT_CENTER ) m_channelMap[index++] = PCM_TOP_FRONT_CENTER ;+ if (m_pCodecContext->channel_layout & CH_TOP_FRONT_RIGHT ) m_channelMap[index++] = PCM_TOP_FRONT_RIGHT ;+ if (m_pCodecContext->channel_layout & CH_TOP_BACK_LEFT ) m_channelMap[index++] = PCM_TOP_BACK_LEFT ;+ if (m_pCodecContext->channel_layout & CH_TOP_BACK_CENTER ) m_channelMap[index++] = PCM_TOP_BACK_CENTER ;+ if (m_pCodecContext->channel_layout & CH_TOP_BACK_RIGHT ) m_channelMap[index++] = PCM_TOP_BACK_RIGHT ; /* if there is less channels in the map then advertised, we need to fix it */ if (index < m_pCodecContext->channels)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); }; #endifIndex: 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;+}+