All pastes #1789700 Raw Edit

Anonymous

public diff v1 · immutable
#1789700 ·published 2010-02-08 02:30 UTC
rendered paste body
Index: 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(&params, 0, sizeof(params));+  params.channels    = hints.channels;+  params.sample_rate = OUT_SAMPLERATE;+  params.channel     = 0;+  if (m_dllAvFormat.av_set_parameters(m_pFormat, &params) != 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(&params, 0, sizeof(params));-    params.channels    = hints.channels;-    params.sample_rate = OUT_SAMPLERATE;-    params.channel     = 0;-    if (m_dllAvFormat.av_set_parameters(m_pFormat, &params) != 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;+}+