2 * Copyright (C) 2010-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "AEPackIEC61937.h"
14 #define IEC61937_PREAMBLE1 0xF872
15 #define IEC61937_PREAMBLE2 0x4E1F
17 inline void SwapEndian(uint16_t *dst
, uint16_t *src
, unsigned int size
)
19 for (unsigned int i
= 0; i
< size
; ++i
, ++dst
, ++src
)
20 *dst
= ((*src
& 0xFF00) >> 8) | ((*src
& 0x00FF) << 8);
23 int CAEPackIEC61937::PackAC3(uint8_t *data
, unsigned int size
, uint8_t *dest
)
25 assert(size
<= OUT_FRAMESTOBYTES(AC3_FRAME_SIZE
));
26 struct IEC61937Packet
*packet
= (struct IEC61937Packet
*)dest
;
28 packet
->m_preamble1
= IEC61937_PREAMBLE1
;
29 packet
->m_preamble2
= IEC61937_PREAMBLE2
;
30 packet
->m_length
= size
<< 3;
33 data
= packet
->m_data
;
36 memcpy(packet
->m_data
, data
, size
);
39 int bitstream_mode
= data
[5] & 0x7;
40 packet
->m_type
= IEC61937_TYPE_AC3
| (bitstream_mode
<< 8);
43 SwapEndian((uint16_t*)packet
->m_data
, (uint16_t*)data
, size
>> 1);
46 memset(packet
->m_data
+ size
, 0, OUT_FRAMESTOBYTES(AC3_FRAME_SIZE
) - IEC61937_DATA_OFFSET
- size
);
47 return OUT_FRAMESTOBYTES(AC3_FRAME_SIZE
);
50 int CAEPackIEC61937::PackEAC3(uint8_t *data
, unsigned int size
, uint8_t *dest
)
52 assert(size
<= OUT_FRAMESTOBYTES(EAC3_FRAME_SIZE
));
53 struct IEC61937Packet
*packet
= (struct IEC61937Packet
*)dest
;
55 packet
->m_preamble1
= IEC61937_PREAMBLE1
;
56 packet
->m_preamble2
= IEC61937_PREAMBLE2
;
57 packet
->m_type
= IEC61937_TYPE_EAC3
;
58 packet
->m_length
= size
;
61 data
= packet
->m_data
;
64 memcpy(packet
->m_data
, data
, size
);
67 SwapEndian((uint16_t*)packet
->m_data
, (uint16_t*)data
, size
>> 1);
70 memset(packet
->m_data
+ size
, 0, OUT_FRAMESTOBYTES(EAC3_FRAME_SIZE
) - IEC61937_DATA_OFFSET
- size
);
71 return OUT_FRAMESTOBYTES(EAC3_FRAME_SIZE
);
74 int CAEPackIEC61937::PackDTS_512(uint8_t *data
, unsigned int size
, uint8_t *dest
, bool littleEndian
)
76 return PackDTS(data
, size
, dest
, littleEndian
, OUT_FRAMESTOBYTES(DTS1_FRAME_SIZE
), IEC61937_TYPE_DTS1
);
79 int CAEPackIEC61937::PackDTS_1024(uint8_t *data
, unsigned int size
, uint8_t *dest
, bool littleEndian
)
81 return PackDTS(data
, size
, dest
, littleEndian
, OUT_FRAMESTOBYTES(DTS2_FRAME_SIZE
), IEC61937_TYPE_DTS2
);
84 int CAEPackIEC61937::PackDTS_2048(uint8_t *data
, unsigned int size
, uint8_t *dest
, bool littleEndian
)
86 return PackDTS(data
, size
, dest
, littleEndian
, OUT_FRAMESTOBYTES(DTS3_FRAME_SIZE
), IEC61937_TYPE_DTS3
);
89 int CAEPackIEC61937::PackTrueHD(const uint8_t* data
, unsigned int size
, uint8_t* dest
)
92 return OUT_FRAMESTOBYTES(TRUEHD_FRAME_SIZE
);
94 assert(size
<= OUT_FRAMESTOBYTES(TRUEHD_FRAME_SIZE
));
95 struct IEC61937Packet
*packet
= (struct IEC61937Packet
*)dest
;
96 packet
->m_preamble1
= IEC61937_PREAMBLE1
;
97 packet
->m_preamble2
= IEC61937_PREAMBLE2
;
98 packet
->m_type
= IEC61937_TYPE_TRUEHD
;
99 packet
->m_length
= 61424;
102 data
= packet
->m_data
;
103 #ifdef __BIG_ENDIAN__
105 memcpy(packet
->m_data
, data
, size
);
108 SwapEndian((uint16_t*)packet
->m_data
, (uint16_t*)data
, size
>> 1);
111 memset(packet
->m_data
+ size
, 0, OUT_FRAMESTOBYTES(TRUEHD_FRAME_SIZE
) - IEC61937_DATA_OFFSET
- size
);
112 return OUT_FRAMESTOBYTES(TRUEHD_FRAME_SIZE
);
115 int CAEPackIEC61937::PackDTSHD(uint8_t *data
, unsigned int size
, uint8_t *dest
, unsigned int period
)
117 unsigned int subtype
;
120 case 512: subtype
= 0; break;
121 case 1024: subtype
= 1; break;
122 case 2048: subtype
= 2; break;
123 case 4096: subtype
= 3; break;
124 case 8192: subtype
= 4; break;
125 case 16384: subtype
= 5; break;
131 struct IEC61937Packet
*packet
= (struct IEC61937Packet
*)dest
;
132 packet
->m_preamble1
= IEC61937_PREAMBLE1
;
133 packet
->m_preamble2
= IEC61937_PREAMBLE2
;
134 packet
->m_type
= IEC61937_TYPE_DTSHD
| (subtype
<< 8);
136 /* Align so that (length_code & 0xf) == 0x8. This is reportedly needed
137 * with some receivers, but the exact requirement is unconfirmed. */
138 packet
->m_length
= ((size
+ 0x17) &~ 0x0f) - 0x08;
141 data
= packet
->m_data
;
142 #ifdef __BIG_ENDIAN__
144 memcpy(packet
->m_data
, data
, size
);
147 SwapEndian((uint16_t*)packet
->m_data
, (uint16_t*)data
, size
>> 1);
150 unsigned int burstsize
= period
<< 2;
151 memset(packet
->m_data
+ size
, 0, burstsize
- IEC61937_DATA_OFFSET
- size
);
155 int CAEPackIEC61937::PackDTS(uint8_t *data
, unsigned int size
, uint8_t *dest
, bool littleEndian
,
156 unsigned int frameSize
, uint16_t type
)
158 assert(size
<= frameSize
);
160 /* BE is the standard endianness, byteswap needed if LE */
161 bool byteSwapNeeded
= littleEndian
;
163 #ifndef __BIG_ENDIAN__
164 /* on LE systems we want LE output, byteswap needed */
165 byteSwapNeeded
^= true;
168 struct IEC61937Packet
*packet
= (struct IEC61937Packet
*)dest
;
171 if (size
== frameSize
)
173 /* No packing possible or needed, DTS stream is suitable for direct output */
176 else if (size
<= frameSize
- IEC61937_DATA_OFFSET
)
178 /* Fits to IEC61937, perform packing */
179 packet
->m_preamble1
= IEC61937_PREAMBLE1
;
180 packet
->m_preamble2
= IEC61937_PREAMBLE2
;
181 packet
->m_type
= type
;
182 packet
->m_length
= size
<< 3;
184 dataTo
= packet
->m_data
;
188 /* Stream is unsuitable for both packing and direct output */
194 else if (!byteSwapNeeded
)
195 memcpy(dataTo
, data
, size
);
200 SwapEndian((uint16_t*)dataTo
, (uint16_t*)data
, size
>> 1);
203 if (size
!= frameSize
)
204 memset(packet
->m_data
+ size
, 0, frameSize
- IEC61937_DATA_OFFSET
- size
);
209 int CAEPackIEC61937::PackPause(uint8_t *dest
, unsigned int millis
, unsigned int framesize
, unsigned int samplerate
, unsigned int rep_period
, unsigned int encodedRate
)
211 int periodInBytes
= rep_period
* framesize
;
212 double periodInTime
= (double)rep_period
/ samplerate
* 1000;
213 int periodsNeeded
= millis
/ periodInTime
;
214 int maxPeriods
= MAX_IEC61937_PACKET
/ periodInBytes
;
215 if (periodsNeeded
> maxPeriods
)
216 periodsNeeded
= maxPeriods
;
217 uint16_t gap
= encodedRate
* millis
/ 1000;
219 struct IEC61937Packet
*packet
= (struct IEC61937Packet
*)dest
;
220 packet
->m_preamble1
= IEC61937_PREAMBLE1
;
221 packet
->m_preamble2
= IEC61937_PREAMBLE2
;
223 packet
->m_length
= 32;
224 memset(packet
->m_data
, 0, periodInBytes
- 8);
226 for (int i
=1; i
<periodsNeeded
; i
++)
228 memcpy(dest
+i
*periodInBytes
, dest
, periodInBytes
);
231 uint16_t *gapPtr
= reinterpret_cast<uint16_t*>(packet
->m_data
);
234 return periodsNeeded
* periodInBytes
;