2 * Copyright (C) 2010-2012 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #include "AEStreamInfo.h"
24 #define IEC61937_PREAMBLE1 0xF872
25 #define IEC61937_PREAMBLE2 0x4E1F
26 #define DTS_PREAMBLE_14BE 0x1FFFE800
27 #define DTS_PREAMBLE_14LE 0xFF1F00E8
28 #define DTS_PREAMBLE_16BE 0x7FFE8001
29 #define DTS_PREAMBLE_16LE 0xFE7F0180
30 #define DTS_PREAMBLE_HD 0x64582025
31 #define DTS_SFREQ_COUNT 16
32 #define MAX_EAC3_BLOCKS 6
34 static enum AEChannel OutputMaps[2][9] = {
35 {AE_CH_RAW, AE_CH_RAW, AE_CH_NULL},
36 {AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_RAW, AE_CH_NULL}
39 static const uint16_t AC3Bitrates [] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640};
40 static const uint16_t AC3FSCod [] = {48000, 44100, 32000, 0};
41 static const uint8_t AC3BlkCod [] = {1, 2, 3, 6};
42 static const uint8_t AC3Channels [] = {2, 1, 2, 3, 3, 4, 4, 5};
43 static const uint8_t DTSChannels [] = {1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8};
44 static const uint8_t THDChanMap [] = {2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1};
46 static const uint32_t DTSSampleRates[DTS_SFREQ_COUNT] =
66 CAEStreamInfo::CAEStreamInfo() :
71 m_syncFunc (&CAEStreamInfo::DetectType),
75 m_dataType (STREAM_TYPE_NULL),
79 m_dllAvUtil.av_crc_init(m_crcTrueHD, 0, 16, 0x2D, sizeof(m_crcTrueHD));
82 CAEStreamInfo::~CAEStreamInfo()
87 int CAEStreamInfo::AddData(uint8_t *data, unsigned int size, uint8_t **buffer/* = NULL */, unsigned int *bufferSize/* = 0 */)
96 unsigned int consumed = 0;
99 unsigned int canSkip = std::min(size, m_skipBytes);
100 unsigned int room = sizeof(m_buffer) - m_bufferSize;
101 unsigned int copy = std::min(room, canSkip);
103 memcpy(m_buffer + m_bufferSize, data, copy);
104 m_bufferSize += copy;
114 GetPacket(buffer, bufferSize);
119 unsigned int offset = 0;
120 unsigned int room = sizeof(m_buffer) - m_bufferSize;
130 unsigned int copy = std::min(room, size);
131 memcpy(m_buffer + m_bufferSize, data, copy);
132 m_bufferSize += copy;
138 if (m_needBytes > m_bufferSize)
142 offset = (this->*m_syncFunc)(m_buffer, m_bufferSize);
144 if (m_hasSync || m_needBytes)
149 m_syncFunc = &CAEStreamInfo::DetectType;
150 m_dataType = STREAM_TYPE_NULL;
154 /* if the buffer is full, or the offset < the buffer size */
155 if (m_bufferSize == sizeof(m_buffer) || offset < m_bufferSize)
157 m_bufferSize -= offset;
159 memmove(m_buffer, m_buffer + offset, m_bufferSize);
164 /* if we got here, we acquired sync on the buffer */
166 /* align the buffer */
169 m_bufferSize -= offset;
170 memmove(m_buffer, m_buffer + offset, m_bufferSize);
173 /* bytes to skip until the next packet */
174 m_skipBytes = std::max(0, (int)m_fsize - (int)m_bufferSize);
183 GetPacket(buffer, bufferSize);
189 void CAEStreamInfo::GetPacket(uint8_t **buffer, unsigned int *bufferSize)
191 /* if the caller wants the packet */
194 /* if it is dtsHD and we only want the core, just fetch that */
195 unsigned int size = m_fsize;
196 if (m_dataType == STREAM_TYPE_DTSHD_CORE)
199 /* make sure the buffer is allocated and big enough */
200 if (!*buffer || !bufferSize || *bufferSize < size)
203 *buffer = new uint8_t[size];
206 /* copy the data into the buffer and update the size */
207 memcpy(*buffer, m_buffer, size);
212 /* remove the parsed data from the buffer */
213 m_bufferSize -= m_fsize;
214 memmove(m_buffer, m_buffer + m_fsize, m_bufferSize);
222 This function looks for sync words across the types in paralell, and only does an exhaustive
223 test if it finds a syncword. Once sync has been established, the relevent sync function sets
224 m_syncFunc to itself. This function will only be called again if total sync is lost, which
225 allows is to switch stream types on the fly much like a real reicever does.
227 unsigned int CAEStreamInfo::DetectType(uint8_t *data, unsigned int size)
229 unsigned int skipped = 0;
230 unsigned int possible = 0;
234 /* if it could be DTS */
235 unsigned int header = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
236 if (header == DTS_PREAMBLE_14LE ||
237 header == DTS_PREAMBLE_14BE ||
238 header == DTS_PREAMBLE_16LE ||
239 header == DTS_PREAMBLE_16BE)
241 unsigned int skip = SyncDTS(data, size);
242 if (m_hasSync || m_needBytes)
243 return skipped + skip;
248 /* if it could be AC3 */
249 if (data[0] == 0x0b && data[1] == 0x77)
251 unsigned int skip = SyncAC3(data, size);
253 return skipped + skip;
258 /* if it could be TrueHD */
259 if (data[4] == 0xf8 && data[5] == 0x72 && data[6] == 0x6f && data[7] == 0xba)
261 unsigned int skip = SyncTrueHD(data, size);
263 return skipped + skip;
268 /* move along one byte */
274 return possible ? possible : skipped;
277 unsigned int CAEStreamInfo::SyncAC3(uint8_t *data, unsigned int size)
279 unsigned int skip = 0;
281 for (; size - skip > 7; ++skip, ++data)
283 /* search for an ac3 sync word */
284 if (data[0] != 0x0b || data[1] != 0x77)
287 uint8_t bsid = data[5] >> 3;
288 uint8_t acmod = data[6] >> 5;
292 if ((acmod & 0x1) && (acmod != 0x1))
299 lfeon = (data[7] & 0x64) ? 1 : 0;
301 lfeon = ((data[6] >> pos) & 0x1) ? 1 : 0;
303 if (bsid > 0x11 || acmod > 8)
310 uint8_t fscod = data[4] >> 6;
311 uint8_t frmsizecod = data[4] & 0x3F;
312 if (fscod == 3 || frmsizecod > 37)
315 /* get the details we need to check crc1 and framesize */
316 unsigned int bitRate = AC3Bitrates[frmsizecod >> 1];
317 unsigned int framesize = 0;
320 case 0: framesize = bitRate * 2; break;
321 case 1: framesize = (320 * bitRate / 147 + (frmsizecod & 1 ? 1 : 0)); break;
322 case 2: framesize = bitRate * 4; break;
325 m_fsize = framesize << 1;
326 m_sampleRate = AC3FSCod[fscod];
328 /* dont do extensive testing if we have not lost sync */
329 if (m_dataType == STREAM_TYPE_AC3 && skip == 0)
332 unsigned int crc_size;
333 /* if we have enough data, validate the entire packet, else try to validate crc2 (5/8 of the packet) */
334 if (framesize <= size - skip)
335 crc_size = framesize - 1;
337 crc_size = (framesize >> 1) + (framesize >> 3) - 1;
339 if (crc_size <= size - skip)
340 if (m_dllAvUtil.av_crc(m_dllAvUtil.av_crc_get_table(AV_CRC_16_ANSI), 0, &data[2], crc_size * 2))
343 /* if we get here, we can sync */
345 m_outputRate = m_sampleRate;
346 m_outputChannels = 2;
347 m_channelMap = CAEChannelInfo(OutputMaps[0]);
348 m_channels = AC3Channels[acmod] + lfeon;
349 m_syncFunc = &CAEStreamInfo::SyncAC3;
350 m_dataType = STREAM_TYPE_AC3;
351 m_packFunc = &CAEPackIEC61937::PackAC3;
354 CLog::Log(LOGINFO, "CAEStreamInfo::SyncAC3 - AC3 stream detected (%d channels, %dHz)", m_channels, m_sampleRate);
360 uint8_t strmtyp = data[2] >> 6;
364 unsigned int framesize = (((data[2] & 0x7) << 8) | data[3]) + 1;
365 uint8_t fscod = (data[4] >> 6) & 0x3;
366 uint8_t cod = (data[4] >> 4) & 0x3;
375 m_sampleRate = AC3FSCod[cod] >> 1;
379 blocks = AC3BlkCod[cod ];
380 m_sampleRate = AC3FSCod [fscod];
383 m_fsize = framesize << 1;
384 m_repeat = MAX_EAC3_BLOCKS / blocks;
386 if (m_sampleRate == 48000 || m_sampleRate == 96000 || m_sampleRate == 192000)
387 m_outputRate = 192000;
389 m_outputRate = 176400;
391 if (m_dataType == STREAM_TYPE_EAC3 && m_hasSync && skip == 0)
394 /* if we get here, we can sync */
396 m_outputChannels = 8;
397 m_channelMap = CAEChannelInfo(OutputMaps[1]);
398 m_channels = 8; /* FIXME: this should be read out of the stream */
399 m_syncFunc = &CAEStreamInfo::SyncAC3;
400 m_dataType = STREAM_TYPE_EAC3;
401 m_packFunc = &CAEPackIEC61937::PackEAC3;
403 CLog::Log(LOGINFO, "CAEStreamInfo::SyncAC3 - E-AC3 stream detected (%d channels, %dHz)", m_channels, m_sampleRate);
408 /* if we get here, the entire packet is invalid and we have lost sync */
409 CLog::Log(LOGINFO, "CAEStreamInfo::SyncAC3 - AC3 sync lost");
414 unsigned int CAEStreamInfo::SyncDTS(uint8_t *data, unsigned int size)
418 if (m_needBytes < 13)
423 unsigned int skip = 0;
424 for (; size - skip > 13; ++skip, ++data)
426 unsigned int header = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
427 unsigned int hd_sync = 0;
429 unsigned int dtsBlocks;
438 case DTS_PREAMBLE_14BE:
439 if (data[4] != 0x07 || (data[5] & 0xf0) != 0xf0)
444 dtsBlocks = (((data[5] & 0x7) << 4) | ((data[6] & 0x3C) >> 2)) + 1;
445 m_fsize = ((((data[6] & 0x3 << 8) | data[7]) << 4) | ((data[8] & 0x3C) >> 2)) + 1;
446 amode = ((data[8] & 0x3) << 4) | ((data[9] & 0xF0) >> 4);
447 sfreq = data[9] & 0xF;
448 lfe = (data[12] & 0x18) >> 3;
454 case DTS_PREAMBLE_14LE:
455 if (data[5] != 0x07 || (data[4] & 0xf0) != 0xf0)
460 dtsBlocks = (((data[4] & 0x7) << 4) | ((data[7] & 0x3C) >> 2)) + 1;
461 m_fsize = ((((data[7] & 0x3 << 8) | data[6]) << 4) | ((data[9] & 0x3C) >> 2)) + 1;
462 amode = ((data[9] & 0x3) << 4) | ((data[8] & 0xF0) >> 4);
463 sfreq = data[8] & 0xF;
464 lfe = (data[13] & 0x18) >> 3;
470 case DTS_PREAMBLE_16BE:
471 dtsBlocks = (((data[4] & 0x1) << 7) | ((data[5] & 0xFC) >> 2)) + 1;
472 m_fsize = (((((data[5] & 0x3) << 8) | data[6]) << 4) | ((data[7] & 0xF0) >> 4)) + 1;
473 amode = ((data[7] & 0x0F) << 2) | ((data[8] & 0xC0) >> 6);
474 sfreq = (data[8] & 0x3C) >> 2;
475 lfe = (data[10] >> 1) & 0x3;
481 case DTS_PREAMBLE_16LE:
482 dtsBlocks = (((data[5] & 0x1) << 7) | ((data[4] & 0xFC) >> 2)) + 1;
483 m_fsize = (((((data[4] & 0x3) << 8) | data[7]) << 4) | ((data[6] & 0xF0) >> 4)) + 1;
484 amode = ((data[6] & 0x0F) << 2) | ((data[9] & 0xC0) >> 6);
485 sfreq = (data[9] & 0x3C) >> 2;
486 lfe = (data[11] >> 1) & 0x3;
496 if (!match || sfreq == 0 || sfreq >= DTS_SFREQ_COUNT)
499 /* make sure the framesize is sane */
500 if (m_fsize < 96 || m_fsize > 16384)
503 bool invalid = false;
505 switch (dtsBlocks << 5)
507 case 512 : dataType = STREAM_TYPE_DTS_512 ; m_packFunc = &CAEPackIEC61937::PackDTS_512 ; break;
508 case 1024: dataType = STREAM_TYPE_DTS_1024; m_packFunc = &CAEPackIEC61937::PackDTS_1024; break;
509 case 2048: dataType = STREAM_TYPE_DTS_2048; m_packFunc = &CAEPackIEC61937::PackDTS_2048; break;
518 /* adjust the fsize for 14 bit streams */
520 m_fsize = m_fsize / 14 * 16;
522 /* we need enough data to check for DTS-HD */
523 if (size - skip < m_fsize + 10)
525 /* we can assume DTS sync at this point */
526 m_syncFunc = &CAEStreamInfo::SyncDTS;
527 m_needBytes = m_fsize + 10;
533 /* look for DTS-HD */
534 hd_sync = (data[m_fsize] << 24) | (data[m_fsize + 1] << 16) | (data[m_fsize + 2] << 8) | data[m_fsize + 3];
535 if (hd_sync == DTS_PREAMBLE_HD)
538 bool blownup = (data[m_fsize + 5] & 0x20) != 0;
540 hd_size = (((data[m_fsize + 6] & 0x01) << 19) | (data[m_fsize + 7] << 11) | (data[m_fsize + 8] << 3) | ((data[m_fsize + 9] & 0xe0) >> 5)) + 1;
542 hd_size = (((data[m_fsize + 6] & 0x1f) << 11) | (data[m_fsize + 7] << 3) | ((data[m_fsize + 8] & 0xe0) >> 5)) + 1;
544 /* set the type according to core or not */
546 dataType = STREAM_TYPE_DTSHD_CORE;
548 dataType = STREAM_TYPE_DTSHD;
550 m_coreSize = m_fsize;
554 unsigned int sampleRate = DTSSampleRates[sfreq];
555 if (!m_hasSync || skip || dataType != m_dataType || sampleRate != m_sampleRate || dtsBlocks != m_dtsBlocks)
558 m_dataType = dataType;
559 m_sampleRate = sampleRate;
560 m_dtsBlocks = dtsBlocks;
561 m_channels = DTSChannels[amode] + (lfe ? 1 : 0);
562 m_syncFunc = &CAEStreamInfo::SyncDTS;
565 if (dataType == STREAM_TYPE_DTSHD)
567 m_outputRate = 192000;
568 m_outputChannels = 8;
569 m_channelMap = CAEChannelInfo(OutputMaps[1]);
570 m_channels += 2; /* FIXME: this needs to be read out, not sure how to do that yet */
574 m_outputRate = m_sampleRate;
575 m_outputChannels = 2;
576 m_channelMap = CAEChannelInfo(OutputMaps[0]);
582 case STREAM_TYPE_DTSHD : type = "dtsHD"; break;
583 case STREAM_TYPE_DTSHD_CORE: type = "dtsHD (core)"; break;
584 default : type = "dts"; break;
587 /* calculate the period size for dtsHD */
588 m_dtsPeriod = (m_outputRate * (m_outputChannels >> 1)) * (m_dtsBlocks << 5) / m_sampleRate;
590 CLog::Log(LOGINFO, "CAEStreamInfo::SyncDTS - %s stream detected (%d channels, %dHz, %dbit %s, period: %u)",
591 type.c_str(), m_channels, m_sampleRate,
592 bits, m_dataIsLE ? "LE" : "BE",
600 CLog::Log(LOGINFO, "CAEStreamInfo::SyncDTS - DTS sync lost");
605 inline unsigned int CAEStreamInfo::GetTrueHDChannels(const uint16_t chanmap)
608 for (int i = 0; i < 13; ++i)
609 channels += THDChanMap[i] * ((chanmap >> i) & 1);
613 unsigned int CAEStreamInfo::SyncTrueHD(uint8_t *data, unsigned int size)
615 unsigned int left = size;
616 unsigned int skip = 0;
619 for (; left; ++skip, ++data, --left)
621 /* if we dont have sync and there is less the 8 bytes, then break out */
622 if (!m_hasSync && left < 8)
625 /* if its a major audio unit */
626 uint16_t length = ((data[0] & 0x0F) << 8 | data[1]) << 1;
627 uint32_t syncword = ((((data[4] << 8 | data[5]) << 8) | data[6]) << 8) | data[7];
628 if (syncword == 0xf8726fba)
630 /* we need 32 bytes to sync on a master audio unit */
634 /* get the rate and ensure its valid */
635 int rate = (data[8] & 0xf0) >> 4;
639 /* verify the crc of the audio unit */
640 uint16_t crc = m_dllAvUtil.av_crc(m_crcTrueHD, 0, data + 4, 24);
641 crc ^= (data[29] << 8) | data[28];
642 if (((data[31] << 8) | data[30]) != crc)
645 /* get the sample rate and substreams, we have a valid master audio unit */
646 m_sampleRate = (rate & 0x8 ? 44100 : 48000) << (rate & 0x7);
647 m_substreams = (data[20] & 0xF0) >> 4;
649 /* get the number of encoded channels */
650 uint16_t channel_map = ((data[10] & 0x1F) << 8) | data[11];
652 channel_map = (data[9] << 1) | (data[10] >> 7);
653 m_channels = CAEStreamInfo::GetTrueHDChannels(channel_map);
655 if (m_sampleRate == 48000 || m_sampleRate == 96000 || m_sampleRate == 192000)
656 m_outputRate = 192000;
658 m_outputRate = 176400;
661 CLog::Log(LOGINFO, "CAEStreamInfo::SyncTrueHD - TrueHD stream detected (%d channels, %dHz)", m_channels, m_sampleRate);
665 m_dataType = STREAM_TYPE_TRUEHD;
666 m_outputChannels = 8;
667 m_channelMap = CAEChannelInfo(OutputMaps[1]);
668 m_syncFunc = &CAEStreamInfo::SyncTrueHD;
669 m_packFunc = &CAEPackIEC61937::PackTrueHD;
675 /* we cant sink to a subframe until we have the information from a master audio unit */
679 /* if there is not enough data left to verify the packet, just return the skip amount */
680 if (left < (unsigned int)m_substreams * 4)
683 /* verify the parity */
686 for (int i = -1; i < m_substreams; ++i)
690 if (i == -1 || data[p - 2] & 0x80)
697 /* if the parity nibble does not match */
698 if ((((check >> 4) ^ check) & 0xF) != 0xF)
702 CLog::Log(LOGINFO, "CAEStreamInfo::SyncTrueHD - Sync Lost");