Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AE] Fix issues related to endianness in passthrough #973

Merged
merged 6 commits into from Jul 10, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion xbmc/cores/AudioEngine/Engines/CoreAudio/CoreAudioAEHAL.cpp
Expand Up @@ -90,7 +90,9 @@ const char* StreamDescriptionToString(AudioStreamBasicDescription desc, std::str
case kAudioFormat60958AC3: case kAudioFormat60958AC3:
sstr << "[" sstr << "["
<< fourCC << fourCC
<< "] AC-3/DTS for S/PDIF (" << "] AC-3/DTS for S/PDIF "
<< ((desc.mFormatFlags & kAudioFormatFlagIsBigEndian) ? "BE" : "LE")
<< " ("
<< (UInt32)desc.mSampleRate << (UInt32)desc.mSampleRate
<< "Hz)"; << "Hz)";
str = sstr.str(); str = sstr.str();
Expand Down
39 changes: 32 additions & 7 deletions xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp
Expand Up @@ -27,6 +27,7 @@
#include "utils/log.h" #include "utils/log.h"
#include "utils/TimeUtils.h" #include "utils/TimeUtils.h"
#include "utils/MathUtils.h" #include "utils/MathUtils.h"
#include "utils/EndianSwap.h"
#include "threads/SingleLock.h" #include "threads/SingleLock.h"
#include "settings/GUISettings.h" #include "settings/GUISettings.h"
#include "settings/Settings.h" #include "settings/Settings.h"
Expand Down Expand Up @@ -883,6 +884,16 @@ void CSoftAE::Run()
} }
} }


void CSoftAE::AllocateConvIfNeeded(size_t convertedSize)
{
if (m_convertedSize < convertedSize)
{
_aligned_free(m_converted);
m_converted = (uint8_t *)_aligned_malloc(convertedSize, 16);
m_convertedSize = convertedSize;
}
}

void CSoftAE::MixSounds(float *buffer, unsigned int samples) void CSoftAE::MixSounds(float *buffer, unsigned int samples)
{ {
SoundStateList::iterator itt; SoundStateList::iterator itt;
Expand Down Expand Up @@ -981,12 +992,7 @@ void CSoftAE::RunOutputStage()
if (m_convertFn) if (m_convertFn)
{ {
const unsigned int convertedBytes = m_sinkFormat.m_frames * m_sinkFormat.m_frameSize; const unsigned int convertedBytes = m_sinkFormat.m_frames * m_sinkFormat.m_frameSize;
if (m_convertedSize < convertedBytes) AllocateConvIfNeeded(convertedBytes);
{
_aligned_free(m_converted);
m_converted = (uint8_t *)_aligned_malloc(convertedBytes, 16);
m_convertedSize = convertedBytes;
}
m_convertFn((float*)data, needSamples, m_converted); m_convertFn((float*)data, needSamples, m_converted);
data = m_converted; data = m_converted;
} }
Expand All @@ -1000,7 +1006,26 @@ void CSoftAE::RunRawOutputStage()
if(m_buffer.Used() < m_sinkBlockSize) if(m_buffer.Used() < m_sinkBlockSize)
return; return;


int wroteFrames = m_sink->AddPackets((uint8_t*)m_buffer.Raw(m_sinkBlockSize), m_sinkFormat.m_frames); void *data = m_buffer.Raw(m_sinkBlockSize);

if (CAEUtil::S16NeedsByteSwap(AE_FMT_S16NE, m_sinkFormat.m_dataFormat))
{
/*
* It would really be preferable to handle this at packing stage, so that
* it could byteswap the data efficiently without wasting CPU time on
* swapping the huge IEC 61937 zero padding between frames (or not
* byteswap at all, if there are two byteswaps).
*
* Unfortunately packing is done on a higher level and we can't easily
* tell it the needed format from here, so do it here for now (better than
* nothing)...
*/
AllocateConvIfNeeded(m_sinkBlockSize);
Endian_Swap16_buf((uint16_t *)m_converted, (uint16_t *)data, m_sinkBlockSize / 2);
data = m_converted;
}

int wroteFrames = m_sink->AddPackets((uint8_t *)data, m_sinkFormat.m_frames);
m_buffer.Shift(NULL, wroteFrames * m_sinkFormat.m_frameSize); m_buffer.Shift(NULL, wroteFrames * m_sinkFormat.m_frameSize);
} }


Expand Down
2 changes: 2 additions & 0 deletions xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h
Expand Up @@ -192,6 +192,8 @@ class CSoftAE : public IThreadedAE
uint8_t *m_converted; uint8_t *m_converted;
size_t m_convertedSize; size_t m_convertedSize;


void AllocateConvIfNeeded(size_t convertedSize);

/* thread run stages */ /* thread run stages */
void MixSounds (float *buffer, unsigned int samples); void MixSounds (float *buffer, unsigned int samples);
void FinalizeSamples (float *buffer, unsigned int samples); void FinalizeSamples (float *buffer, unsigned int samples);
Expand Down
8 changes: 7 additions & 1 deletion xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
Expand Up @@ -193,13 +193,15 @@ bool CAESinkALSA::IsCompatible(const AEAudioFormat format, const std::string dev
snd_pcm_format_t CAESinkALSA::AEFormatToALSAFormat(const enum AEDataFormat format) snd_pcm_format_t CAESinkALSA::AEFormatToALSAFormat(const enum AEDataFormat format)
{ {
if (AE_IS_RAW(format)) if (AE_IS_RAW(format))
return SND_PCM_FORMAT_S16_LE; return SND_PCM_FORMAT_S16;


switch (format) switch (format)
{ {
case AE_FMT_S8 : return SND_PCM_FORMAT_S8; case AE_FMT_S8 : return SND_PCM_FORMAT_S8;
case AE_FMT_U8 : return SND_PCM_FORMAT_U8; case AE_FMT_U8 : return SND_PCM_FORMAT_U8;
case AE_FMT_S16NE : return SND_PCM_FORMAT_S16; case AE_FMT_S16NE : return SND_PCM_FORMAT_S16;
case AE_FMT_S16LE : return SND_PCM_FORMAT_S16_LE;
case AE_FMT_S16BE : return SND_PCM_FORMAT_S16_BE;
case AE_FMT_S24NE4: return SND_PCM_FORMAT_S24; case AE_FMT_S24NE4: return SND_PCM_FORMAT_S24;
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
case AE_FMT_S24NE3: return SND_PCM_FORMAT_S24_3BE; case AE_FMT_S24NE3: return SND_PCM_FORMAT_S24_3BE;
Expand Down Expand Up @@ -258,6 +260,10 @@ bool CAESinkALSA::InitializeHW(AEAudioFormat &format)
{ {
if (AE_IS_RAW(i) || i == AE_FMT_MAX) if (AE_IS_RAW(i) || i == AE_FMT_MAX)
continue; continue;

if (m_passthrough && i != AE_FMT_S16BE && i != AE_FMT_S16LE)
continue;

fmt = AEFormatToALSAFormat(i); fmt = AEFormatToALSAFormat(i);


if (fmt == SND_PCM_FORMAT_UNKNOWN || snd_pcm_hw_params_set_format(m_pcm, hw_params, fmt) < 0) if (fmt == SND_PCM_FORMAT_UNKNOWN || snd_pcm_hw_params_set_format(m_pcm, hw_params, fmt) < 0)
Expand Down
13 changes: 13 additions & 0 deletions xbmc/cores/AudioEngine/Utils/AEBitstreamPacker.cpp
Expand Up @@ -20,6 +20,7 @@
*/ */


#include "AEBitstreamPacker.h" #include "AEBitstreamPacker.h"
#include "AEPackIEC61937.h"
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
Expand Down Expand Up @@ -56,6 +57,18 @@ void CAEBitstreamPacker::Pack(CAEStreamInfo &info, uint8_t* data, int size)
PackDTSHD (info, data, size); PackDTSHD (info, data, size);
break; break;


case CAEStreamInfo::STREAM_TYPE_DTS_512:
m_dataSize = CAEPackIEC61937::PackDTS_512(data, size, m_packedBuffer, info.IsLittleEndian());
break;

case CAEStreamInfo::STREAM_TYPE_DTS_1024:
m_dataSize = CAEPackIEC61937::PackDTS_1024(data, size, m_packedBuffer, info.IsLittleEndian());
break;

case CAEStreamInfo::STREAM_TYPE_DTS_2048:
m_dataSize = CAEPackIEC61937::PackDTS_2048(data, size, m_packedBuffer, info.IsLittleEndian());
break;

default: default:
/* pack the data into an IEC61937 frame */ /* pack the data into an IEC61937 frame */
CAEPackIEC61937::PackFunc pack = info.GetPackFunc(); CAEPackIEC61937::PackFunc pack = info.GetPackFunc();
Expand Down
2 changes: 0 additions & 2 deletions xbmc/cores/AudioEngine/Utils/AEConvert.h
Expand Up @@ -23,8 +23,6 @@
#include <stdint.h> #include <stdint.h>
#include "../AEAudioFormat.h" #include "../AEAudioFormat.h"


/* note: always converts to machine byte endian */

class CAEConvert{ class CAEConvert{
private: private:
static unsigned int U8_Float (uint8_t *data, const unsigned int samples, float *dest); static unsigned int U8_Float (uint8_t *data, const unsigned int samples, float *dest);
Expand Down
121 changes: 59 additions & 62 deletions xbmc/cores/AudioEngine/Utils/AEPackIEC61937.cpp
Expand Up @@ -19,8 +19,6 @@
* *
*/ */


/* DTS spec shows it suppors both BE and LE, we should not need to convert */

#include <cassert> #include <cassert>
#include "system.h" #include "system.h"
#include "AEPackIEC61937.h" #include "AEPackIEC61937.h"
Expand Down Expand Up @@ -85,73 +83,19 @@ int CAEPackIEC61937::PackEAC3(uint8_t *data, unsigned int size, uint8_t *dest)
return OUT_FRAMESTOBYTES(EAC3_FRAME_SIZE); return OUT_FRAMESTOBYTES(EAC3_FRAME_SIZE);
} }


int CAEPackIEC61937::PackDTS_512(uint8_t *data, unsigned int size, uint8_t *dest) int CAEPackIEC61937::PackDTS_512(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian)
{ {
assert(size <= OUT_FRAMESTOBYTES(DTS1_FRAME_SIZE)); return PackDTS(data, size, dest, littleEndian, OUT_FRAMESTOBYTES(DTS1_FRAME_SIZE), IEC61937_TYPE_DTS1);
struct IEC61937Packet *packet = (struct IEC61937Packet*)dest;
packet->m_preamble1 = IEC61937_PREAMBLE1;
packet->m_preamble2 = IEC61937_PREAMBLE2;
packet->m_type = IEC61937_TYPE_DTS1;
packet->m_length = size << 3;

if (data == NULL)
data = packet->m_data;
#ifdef __BIG_ENDIAN__
else
memcpy(packet->m_data, data, size);
#else
size += size & 0x1;
SwapEndian((uint16_t*)packet->m_data, (uint16_t*)data, size >> 1);
#endif

memset(packet->m_data + size, 0, OUT_FRAMESTOBYTES(DTS1_FRAME_SIZE) - IEC61937_DATA_OFFSET - size);
return OUT_FRAMESTOBYTES(DTS1_FRAME_SIZE);
} }


int CAEPackIEC61937::PackDTS_1024(uint8_t *data, unsigned int size, uint8_t *dest) int CAEPackIEC61937::PackDTS_1024(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian)
{ {
assert(size <= OUT_FRAMESTOBYTES(DTS2_FRAME_SIZE)); return PackDTS(data, size, dest, littleEndian, OUT_FRAMESTOBYTES(DTS2_FRAME_SIZE), IEC61937_TYPE_DTS2);
struct IEC61937Packet *packet = (struct IEC61937Packet*)dest;
packet->m_preamble1 = IEC61937_PREAMBLE1;
packet->m_preamble2 = IEC61937_PREAMBLE2;
packet->m_type = IEC61937_TYPE_DTS2;
packet->m_length = size << 3;

if (data == NULL)
data = packet->m_data;
#ifdef __BIG_ENDIAN__
else
memcpy(packet->m_data, data, size);
#else
size += size & 0x1;
SwapEndian((uint16_t*)packet->m_data, (uint16_t*)data, size >> 1);
#endif

memset(packet->m_data + size, 0, OUT_FRAMESTOBYTES(DTS2_FRAME_SIZE) - IEC61937_DATA_OFFSET - size);
return OUT_FRAMESTOBYTES(DTS2_FRAME_SIZE);
} }


int CAEPackIEC61937::PackDTS_2048(uint8_t *data, unsigned int size, uint8_t *dest) int CAEPackIEC61937::PackDTS_2048(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian)
{ {
assert(size <= OUT_FRAMESTOBYTES(DTS3_FRAME_SIZE)); return PackDTS(data, size, dest, littleEndian, OUT_FRAMESTOBYTES(DTS3_FRAME_SIZE), IEC61937_TYPE_DTS3);
struct IEC61937Packet *packet = (struct IEC61937Packet*)dest;
packet->m_preamble1 = IEC61937_PREAMBLE1;
packet->m_preamble2 = IEC61937_PREAMBLE2;
packet->m_type = IEC61937_TYPE_DTS3;
packet->m_length = size << 3;

if (data == NULL)
data = packet->m_data;
#ifdef __BIG_ENDIAN__
else
memcpy(packet->m_data, data, size);
#else
size += size & 0x1;
SwapEndian((uint16_t*)packet->m_data, (uint16_t*)data, size >> 1);
#endif

memset(packet->m_data + size, 0, OUT_FRAMESTOBYTES(DTS3_FRAME_SIZE) - IEC61937_DATA_OFFSET - size);
return OUT_FRAMESTOBYTES(DTS3_FRAME_SIZE);
} }


int CAEPackIEC61937::PackTrueHD(uint8_t *data, unsigned int size, uint8_t *dest) int CAEPackIEC61937::PackTrueHD(uint8_t *data, unsigned int size, uint8_t *dest)
Expand Down Expand Up @@ -220,3 +164,56 @@ int CAEPackIEC61937::PackDTSHD(uint8_t *data, unsigned int size, uint8_t *dest,
return burstsize; return burstsize;
} }


int CAEPackIEC61937::PackDTS(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian,
unsigned int frameSize, uint16_t type)
{
assert(size <= frameSize);

/* BE is the standard endianness, byteswap needed if LE */
bool byteSwapNeeded = littleEndian;

#ifndef __BIG_ENDIAN__
/* on LE systems we want LE output, byteswap needed */
byteSwapNeeded ^= true;
#endif

struct IEC61937Packet *packet = (struct IEC61937Packet*)dest;
uint8_t *dataTo;

if (size == frameSize)
{
/* No packing possible or needed, DTS stream is suitable for direct output */
dataTo = dest;
}
else if (size <= frameSize - IEC61937_DATA_OFFSET)
{
/* Fits to IEC61937, perform packing */
packet->m_preamble1 = IEC61937_PREAMBLE1;
packet->m_preamble2 = IEC61937_PREAMBLE2;
packet->m_type = type;
packet->m_length = size << 3;

dataTo = packet->m_data;
}
else
{
/* Stream is unsuitable for both packing and direct output */
return 0;
}

if (data == NULL)
data = dataTo;
else if (!byteSwapNeeded)
memcpy(dataTo, data, size);

if (byteSwapNeeded)
{
size += size & 0x1;
SwapEndian((uint16_t*)dataTo, (uint16_t*)data, size >> 1);
}

if (size != frameSize)
memset(packet->m_data + size, 0, frameSize - IEC61937_DATA_OFFSET - size);

return frameSize;
}
10 changes: 7 additions & 3 deletions xbmc/cores/AudioEngine/Utils/AEPackIEC61937.h
Expand Up @@ -52,12 +52,16 @@ class CAEPackIEC61937


static int PackAC3 (uint8_t *data, unsigned int size, uint8_t *dest); static int PackAC3 (uint8_t *data, unsigned int size, uint8_t *dest);
static int PackEAC3 (uint8_t *data, unsigned int size, uint8_t *dest); static int PackEAC3 (uint8_t *data, unsigned int size, uint8_t *dest);
static int PackDTS_512 (uint8_t *data, unsigned int size, uint8_t *dest); static int PackDTS_512 (uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian);
static int PackDTS_1024(uint8_t *data, unsigned int size, uint8_t *dest); static int PackDTS_1024(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian);
static int PackDTS_2048(uint8_t *data, unsigned int size, uint8_t *dest); static int PackDTS_2048(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian);
static int PackTrueHD (uint8_t *data, unsigned int size, uint8_t *dest); static int PackTrueHD (uint8_t *data, unsigned int size, uint8_t *dest);
static int PackDTSHD (uint8_t *data, unsigned int size, uint8_t *dest, unsigned int period); static int PackDTSHD (uint8_t *data, unsigned int size, uint8_t *dest, unsigned int period);
private: private:

static int PackDTS(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian,
unsigned int frameSize, uint16_t type);

enum IEC61937DataType enum IEC61937DataType
{ {
IEC61937_TYPE_NULL = 0x00, IEC61937_TYPE_NULL = 0x00,
Expand Down
6 changes: 3 additions & 3 deletions xbmc/cores/AudioEngine/Utils/AEStreamInfo.cpp
Expand Up @@ -504,9 +504,9 @@ unsigned int CAEStreamInfo::SyncDTS(uint8_t *data, unsigned int size)
DataType dataType; DataType dataType;
switch (dtsBlocks << 5) switch (dtsBlocks << 5)
{ {
case 512 : dataType = STREAM_TYPE_DTS_512 ; m_packFunc = &CAEPackIEC61937::PackDTS_512 ; break; case 512 : dataType = STREAM_TYPE_DTS_512 ; break;
case 1024: dataType = STREAM_TYPE_DTS_1024; m_packFunc = &CAEPackIEC61937::PackDTS_1024; break; case 1024: dataType = STREAM_TYPE_DTS_1024; break;
case 2048: dataType = STREAM_TYPE_DTS_2048; m_packFunc = &CAEPackIEC61937::PackDTS_2048; break; case 2048: dataType = STREAM_TYPE_DTS_2048; break;
default: default:
invalid = true; invalid = true;
break; break;
Expand Down
17 changes: 17 additions & 0 deletions xbmc/cores/AudioEngine/Utils/AEUtil.cpp
Expand Up @@ -455,3 +455,20 @@ void CAEUtil::FloatRand4(const float min, const float max, float result[4], __m1
result[3] = ((float)(m_seed = (214013 * m_seed + 2531011)) * factor) - delta; result[3] = ((float)(m_seed = (214013 * m_seed + 2531011)) * factor) - delta;
#endif #endif
} }

bool CAEUtil::S16NeedsByteSwap(AEDataFormat in, AEDataFormat out)
{
const AEDataFormat nativeFormat =
#ifdef WORDS_BIGENDIAN
AE_FMT_S16BE;
#else
AE_FMT_S16LE;
#endif

if (in == AE_FMT_S16NE || AE_IS_RAW(in))
in = nativeFormat;
if (out == AE_FMT_S16NE || AE_IS_RAW(out))
out = nativeFormat;

return in != out;
}

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

2 changes: 2 additions & 0 deletions xbmc/cores/AudioEngine/Utils/AEUtil.h
Expand Up @@ -74,4 +74,6 @@ class CAEUtil
*/ */
static float FloatRand1(const float min, const float max); static float FloatRand1(const float min, const float max);
static void FloatRand4(const float min, const float max, float result[4], __m128 *sseresult = NULL); static void FloatRand4(const float min, const float max, float result[4], __m128 *sseresult = NULL);

static bool S16NeedsByteSwap(AEDataFormat in, AEDataFormat out);
}; };