Permalink
Browse files

[AE] fixed: passthrough of LE DTS, pre-padded DTS, invalid DTS

AEPackIEC61937 currently doesn't take into account that LE DTS needs to
be byteswapped to BE format (in addition to any other byteswaps) before
being transmitted to the receiver, as only the BE format is standard and
supported by all receivers. Code comment says that the "DTS spec shows
it suppors both BE and LE", but in reality there is no provision for LE
in the DTS specification.

Additionally, AEPackIEC61937 doesn't properly handle DTS streams that
are pre-padded for S/PDIF transmission. Such streams fit exactly into
the output S/PDIF stream and no padding or IEC61937 wrapping is needed
(there is not enough space for those, either).

Also, frame size is not validated properly. Valid DTS frame sizes
in the range [ BurstPeriod-BurstHeader+1 , BurstPeriod-1 ] cannot be
packed into IEC 61937 as there is no space for the burst header.
Currently the code crashes with such inputs.

Fix all three issues by adding code handling them.
  • Loading branch information...
anssih committed May 17, 2012
1 parent 1d42f5e commit 941eae2dde7d57f7dc55334800b47cc0db45ada9
@@ -20,6 +20,7 @@
*/
#include "AEBitstreamPacker.h"
+#include "AEPackIEC61937.h"
#include <stdint.h>
#include <stddef.h>
#include <string.h>
@@ -56,6 +57,18 @@ void CAEBitstreamPacker::Pack(CAEStreamInfo &info, uint8_t* data, int size)
PackDTSHD (info, data, size);
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:
/* pack the data into an IEC61937 frame */
CAEPackIEC61937::PackFunc pack = info.GetPackFunc();
@@ -19,8 +19,6 @@
*
*/
-/* DTS spec shows it suppors both BE and LE, we should not need to convert */
-
#include <cassert>
#include "system.h"
#include "AEPackIEC61937.h"
@@ -85,73 +83,19 @@ int CAEPackIEC61937::PackEAC3(uint8_t *data, unsigned int size, uint8_t *dest)
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));
- 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);
+ return PackDTS(data, size, dest, littleEndian, OUT_FRAMESTOBYTES(DTS1_FRAME_SIZE), IEC61937_TYPE_DTS1);
}
-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));
- 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);
+ return PackDTS(data, size, dest, littleEndian, OUT_FRAMESTOBYTES(DTS2_FRAME_SIZE), IEC61937_TYPE_DTS2);
}
-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));
- 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);
+ return PackDTS(data, size, dest, littleEndian, OUT_FRAMESTOBYTES(DTS3_FRAME_SIZE), IEC61937_TYPE_DTS3);
}
int CAEPackIEC61937::PackTrueHD(uint8_t *data, unsigned int size, uint8_t *dest)
@@ -220,3 +164,56 @@ int CAEPackIEC61937::PackDTSHD(uint8_t *data, unsigned int size, uint8_t *dest,
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;
+}
@@ -52,12 +52,16 @@ class CAEPackIEC61937
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 PackDTS_512 (uint8_t *data, unsigned int size, uint8_t *dest);
- static int PackDTS_1024(uint8_t *data, unsigned int size, uint8_t *dest);
- static int PackDTS_2048(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, bool littleEndian);
+ 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 PackDTSHD (uint8_t *data, unsigned int size, uint8_t *dest, unsigned int period);
private:
+
+ static int PackDTS(uint8_t *data, unsigned int size, uint8_t *dest, bool littleEndian,
+ unsigned int frameSize, uint16_t type);
+
enum IEC61937DataType
{
IEC61937_TYPE_NULL = 0x00,
@@ -504,9 +504,9 @@ unsigned int CAEStreamInfo::SyncDTS(uint8_t *data, unsigned int size)
DataType dataType;
switch (dtsBlocks << 5)
{
- case 512 : dataType = STREAM_TYPE_DTS_512 ; m_packFunc = &CAEPackIEC61937::PackDTS_512 ; break;
- case 1024: dataType = STREAM_TYPE_DTS_1024; m_packFunc = &CAEPackIEC61937::PackDTS_1024; break;
- case 2048: dataType = STREAM_TYPE_DTS_2048; m_packFunc = &CAEPackIEC61937::PackDTS_2048; break;
+ case 512 : dataType = STREAM_TYPE_DTS_512 ; break;
+ case 1024: dataType = STREAM_TYPE_DTS_1024; break;
+ case 2048: dataType = STREAM_TYPE_DTS_2048; break;
default:
invalid = true;
break;

0 comments on commit 941eae2

Please sign in to comment.