[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / cores / AudioEngine / Utils / AEStreamInfo.cpp
blob8f49fe9cad072382867be4981bef48ed09d66a87
1 /*
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.
7 */
9 #include "AEStreamInfo.h"
11 #include "utils/log.h"
13 #include <algorithm>
14 #include <string.h>
16 #define DTS_PREAMBLE_14BE 0x1FFFE800
17 #define DTS_PREAMBLE_14LE 0xFF1F00E8
18 #define DTS_PREAMBLE_16BE 0x7FFE8001
19 #define DTS_PREAMBLE_16LE 0xFE7F0180
20 #define DTS_PREAMBLE_HD 0x64582025
21 #define DTS_PREAMBLE_XCH 0x5a5a5a5a
22 #define DTS_PREAMBLE_XXCH 0x47004a03
23 #define DTS_PREAMBLE_X96K 0x1d95f262
24 #define DTS_PREAMBLE_XBR 0x655e315e
25 #define DTS_PREAMBLE_LBR 0x0a801921
26 #define DTS_PREAMBLE_XLL 0x41a29547
27 #define DTS_SFREQ_COUNT 16
28 #define MAX_EAC3_BLOCKS 6
29 #define UNKNOWN_DTS_EXTENSION 255
31 static const uint16_t AC3Bitrates[] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160,
32 192, 224, 256, 320, 384, 448, 512, 576, 640};
33 static const uint16_t AC3FSCod[] = {48000, 44100, 32000, 0};
34 static const uint8_t AC3BlkCod[] = {1, 2, 3, 6};
35 static const uint8_t AC3Channels[] = {2, 1, 2, 3, 3, 4, 4, 5};
36 static const uint8_t DTSChannels[] = {1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8};
37 static const uint8_t THDChanMap[] = {2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1};
39 static const uint32_t DTSSampleRates[DTS_SFREQ_COUNT] = {0, 8000, 16000, 32000, 64000, 128000,
40 11025, 22050, 44100, 88200, 176400, 12000,
41 24000, 48000, 96000, 192000};
43 CAEStreamParser::CAEStreamParser() : m_syncFunc(&CAEStreamParser::DetectType)
45 av_crc_init(m_crcTrueHD, 0, 16, 0x2D, sizeof(m_crcTrueHD));
48 double CAEStreamInfo::GetDuration() const
50 double duration = 0;
51 switch (m_type)
53 case STREAM_TYPE_AC3:
54 duration = 0.032;
55 break;
56 case STREAM_TYPE_EAC3:
57 duration = 6144.0 / m_sampleRate / 4;
58 break;
59 case STREAM_TYPE_TRUEHD:
60 int rate;
61 if (m_sampleRate == 48000 || m_sampleRate == 96000 || m_sampleRate == 192000)
62 rate = 192000;
63 else
64 rate = 176400;
65 duration = 3840.0 / rate;
66 break;
67 case STREAM_TYPE_DTS_512:
68 case STREAM_TYPE_DTSHD_CORE:
69 case STREAM_TYPE_DTSHD:
70 case STREAM_TYPE_DTSHD_MA:
71 duration = 512.0 / m_sampleRate;
72 break;
73 case STREAM_TYPE_DTS_1024:
74 duration = 1024.0 / m_sampleRate;
75 break;
76 case STREAM_TYPE_DTS_2048:
77 duration = 2048.0 / m_sampleRate;
78 break;
79 default:
80 CLog::Log(LOGERROR, "CAEStreamInfo::GetDuration - invalid stream type");
81 break;
83 return duration * 1000;
86 bool CAEStreamInfo::operator==(const CAEStreamInfo& info) const
88 if (m_type != info.m_type)
89 return false;
90 if (m_dataIsLE != info.m_dataIsLE)
91 return false;
92 if (m_repeat != info.m_repeat)
93 return false;
94 return true;
97 void CAEStreamParser::Reset()
99 m_skipBytes = 0;
100 m_bufferSize = 0;
101 m_needBytes = 0;
102 m_hasSync = false;
105 int CAEStreamParser::AddData(uint8_t* data,
106 unsigned int size,
107 uint8_t** buffer,
108 unsigned int* bufferSize)
110 if (size == 0)
112 if (bufferSize)
113 *bufferSize = 0;
114 return 0;
117 if (m_skipBytes)
119 unsigned int canSkip = std::min(size, m_skipBytes);
120 unsigned int room = sizeof(m_buffer) - m_bufferSize;
121 unsigned int copy = std::min(room, canSkip);
123 memcpy(m_buffer + m_bufferSize, data, copy);
124 m_bufferSize += copy;
125 m_skipBytes -= copy;
127 if (m_skipBytes)
129 if (bufferSize)
130 *bufferSize = 0;
131 return copy;
134 GetPacket(buffer, bufferSize);
135 return copy;
137 else
139 unsigned int consumed = 0;
140 unsigned int offset = 0;
141 unsigned int room = sizeof(m_buffer) - m_bufferSize;
142 while (true)
144 if (!size)
146 if (bufferSize)
147 *bufferSize = 0;
148 return consumed;
151 unsigned int copy = std::min(room, size);
152 memcpy(m_buffer + m_bufferSize, data, copy);
153 m_bufferSize += copy;
154 consumed += copy;
155 data += copy;
156 size -= copy;
157 room -= copy;
159 if (m_needBytes > m_bufferSize)
160 continue;
162 m_needBytes = 0;
163 offset = (this->*m_syncFunc)(m_buffer, m_bufferSize);
165 if (m_hasSync)
166 break;
167 else
169 // lost sync
170 m_syncFunc = &CAEStreamParser::DetectType;
171 m_info.m_type = CAEStreamInfo::STREAM_TYPE_NULL;
172 m_info.m_repeat = 1;
174 // if the buffer is full, or the offset < the buffer size
175 if (m_bufferSize == sizeof(m_buffer) || offset < m_bufferSize)
177 m_bufferSize -= offset;
178 room += offset;
179 memmove(m_buffer, m_buffer + offset, m_bufferSize);
184 // if we got here, we acquired sync on the buffer
186 // align the buffer
187 if (offset)
189 m_bufferSize -= offset;
190 memmove(m_buffer, m_buffer + offset, m_bufferSize);
193 // bytes to skip until the next packet
194 m_skipBytes = std::max(0, (int)m_fsize - (int)m_bufferSize);
195 if (m_skipBytes)
197 if (bufferSize)
198 *bufferSize = 0;
199 return consumed;
202 if (!m_needBytes)
203 GetPacket(buffer, bufferSize);
204 else if (bufferSize)
205 *bufferSize = 0;
207 return consumed;
211 void CAEStreamParser::GetPacket(uint8_t** buffer, unsigned int* bufferSize)
213 // if the caller wants the packet
214 if (buffer)
216 // if it is dtsHD and we only want the core, just fetch that
217 unsigned int size = m_fsize;
218 if (m_info.m_type == CAEStreamInfo::STREAM_TYPE_DTSHD_CORE)
219 size = m_coreSize;
221 // make sure the buffer is allocated and big enough
222 if (!*buffer || !bufferSize || *bufferSize < size)
224 delete[] * buffer;
225 *buffer = new uint8_t[size];
228 // copy the data into the buffer and update the size
229 memcpy(*buffer, m_buffer, size);
230 if (bufferSize)
231 *bufferSize = size;
234 // remove the parsed data from the buffer
235 m_bufferSize -= m_fsize;
236 memmove(m_buffer, m_buffer + m_fsize, m_bufferSize);
237 m_fsize = 0;
238 m_coreSize = 0;
241 // SYNC FUNCTIONS
243 // This function looks for sync words across the types in parallel, and only does an exhaustive
244 // test if it finds a syncword. Once sync has been established, the relevant sync function sets
245 // m_syncFunc to itself. This function will only be called again if total sync is lost, which
246 // allows is to switch stream types on the fly much like a real receiver does.
247 unsigned int CAEStreamParser::DetectType(uint8_t* data, unsigned int size)
249 unsigned int skipped = 0;
250 unsigned int possible = 0;
252 while (size > 8)
254 // if it could be DTS
255 unsigned int header = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
256 if (header == DTS_PREAMBLE_14LE || header == DTS_PREAMBLE_14BE || header == DTS_PREAMBLE_16LE ||
257 header == DTS_PREAMBLE_16BE)
259 unsigned int skip = SyncDTS(data, size);
260 if (m_hasSync || m_needBytes)
261 return skipped + skip;
262 else
263 possible = skipped;
266 // if it could be AC3
267 if (data[0] == 0x0b && data[1] == 0x77)
269 unsigned int skip = SyncAC3(data, size);
270 if (m_hasSync || m_needBytes)
271 return skipped + skip;
272 else
273 possible = skipped;
276 // if it could be TrueHD
277 if (data[4] == 0xf8 && data[5] == 0x72 && data[6] == 0x6f && data[7] == 0xba)
279 unsigned int skip = SyncTrueHD(data, size);
280 if (m_hasSync)
281 return skipped + skip;
282 else
283 possible = skipped;
286 // move along one byte
287 --size;
288 ++skipped;
289 ++data;
292 return possible ? possible : skipped;
295 bool CAEStreamParser::TrySyncAC3(uint8_t* data,
296 unsigned int size,
297 bool resyncing,
298 bool wantEAC3dependent)
300 if (size < 8)
301 return false;
303 // look for an ac3 sync word
304 if (data[0] != 0x0b || data[1] != 0x77)
305 return false;
307 uint8_t bsid = data[5] >> 3;
308 uint8_t acmod = data[6] >> 5;
309 uint8_t lfeon;
311 int8_t pos = 4;
312 if ((acmod & 0x1) && (acmod != 0x1))
313 pos -= 2;
314 if (acmod & 0x4)
315 pos -= 2;
316 if (acmod == 0x2)
317 pos -= 2;
318 if (pos < 0)
319 lfeon = (data[7] & 0x64) ? 1 : 0;
320 else
321 lfeon = ((data[6] >> pos) & 0x1) ? 1 : 0;
323 if (bsid > 0x11 || acmod > 7)
324 return false;
326 if (bsid <= 10)
328 // Normal AC-3
330 if (wantEAC3dependent)
331 return false;
333 uint8_t fscod = data[4] >> 6;
334 uint8_t frmsizecod = data[4] & 0x3F;
335 if (fscod == 3 || frmsizecod > 37)
336 return false;
338 // get the details we need to check crc1 and framesize
339 unsigned int bitRate = AC3Bitrates[frmsizecod >> 1];
340 unsigned int framesize = 0;
341 switch (fscod)
343 case 0:
344 framesize = bitRate * 2;
345 break;
346 case 1:
347 framesize = (320 * bitRate / 147 + (frmsizecod & 1 ? 1 : 0));
348 break;
349 case 2:
350 framesize = bitRate * 4;
351 break;
354 m_fsize = framesize << 1;
355 m_info.m_sampleRate = AC3FSCod[fscod];
357 // dont do extensive testing if we have not lost sync
358 if (m_info.m_type == CAEStreamInfo::STREAM_TYPE_AC3 && !resyncing)
359 return true;
361 // this may be the main stream of EAC3
362 unsigned int fsizeMain = m_fsize;
363 unsigned int reqBytes = fsizeMain + 8;
364 if (size < reqBytes)
366 // not enough data to check for E-AC3 dependent frame, request more
367 m_needBytes = reqBytes;
368 m_fsize = 0;
369 // no need to resync => return true
370 return true;
372 m_info.m_frameSize = fsizeMain;
373 if (TrySyncAC3(data + fsizeMain, size - fsizeMain, resyncing, true))
375 // concatenate the main and dependent frames
376 m_fsize += fsizeMain;
377 return true;
380 unsigned int crc_size;
381 // if we have enough data, validate the entire packet, else try to validate crc2 (5/8 of the packet)
382 if (framesize <= size)
383 crc_size = framesize - 1;
384 else
385 crc_size = (framesize >> 1) + (framesize >> 3) - 1;
387 if (crc_size <= size)
388 if (av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, &data[2], crc_size * 2))
389 return false;
391 // if we get here, we can sync
392 m_hasSync = true;
393 m_info.m_channels = AC3Channels[acmod] + lfeon;
394 m_syncFunc = &CAEStreamParser::SyncAC3;
395 m_info.m_type = CAEStreamInfo::STREAM_TYPE_AC3;
396 m_info.m_frameSize += m_fsize;
397 m_info.m_repeat = 1;
399 CLog::Log(LOGINFO, "CAEStreamParser::TrySyncAC3 - AC3 stream detected ({} channels, {}Hz)",
400 m_info.m_channels, m_info.m_sampleRate);
401 return true;
403 else
405 // Enhanced AC-3
406 uint8_t strmtyp = data[2] >> 6;
407 if (strmtyp == 3)
408 return false;
410 if (strmtyp != 1 && wantEAC3dependent)
411 return false;
413 unsigned int framesize = (((data[2] & 0x7) << 8) | data[3]) + 1;
414 uint8_t fscod = (data[4] >> 6) & 0x3;
415 uint8_t cod = (data[4] >> 4) & 0x3;
416 uint8_t acmod = (data[4] >> 1) & 0x7;
417 uint8_t lfeon = data[4] & 0x1;
418 uint8_t blocks;
420 if (fscod == 0x3)
422 if (cod == 0x3)
423 return false;
425 blocks = 6;
426 m_info.m_sampleRate = AC3FSCod[cod] >> 1;
428 else
430 blocks = AC3BlkCod[cod];
431 m_info.m_sampleRate = AC3FSCod[fscod];
434 m_fsize = framesize << 1;
435 m_info.m_repeat = MAX_EAC3_BLOCKS / blocks;
437 // EAC3 can have a dependent stream too
438 if (!wantEAC3dependent)
440 unsigned int fsizeMain = m_fsize;
441 unsigned int reqBytes = fsizeMain + 8;
442 if (size < reqBytes)
444 // not enough data to check for E-AC3 dependent frame, request more
445 m_needBytes = reqBytes;
446 m_fsize = 0;
447 // no need to resync => return true
448 return true;
450 m_info.m_frameSize = fsizeMain;
451 if (TrySyncAC3(data + fsizeMain, size - fsizeMain, resyncing, true))
453 // concatenate the main and dependent frames
454 m_fsize += fsizeMain;
455 return true;
459 if (m_info.m_type == CAEStreamInfo::STREAM_TYPE_EAC3 && m_hasSync && !resyncing)
460 return true;
462 // if we get here, we can sync
463 m_hasSync = true;
464 m_info.m_channels = AC3Channels[acmod] + lfeon;
465 m_syncFunc = &CAEStreamParser::SyncAC3;
466 m_info.m_type = CAEStreamInfo::STREAM_TYPE_EAC3;
467 m_info.m_frameSize += m_fsize;
469 CLog::Log(LOGINFO, "CAEStreamParser::TrySyncAC3 - E-AC3 stream detected ({} channels, {}Hz)",
470 m_info.m_channels, m_info.m_sampleRate);
471 return true;
475 unsigned int CAEStreamParser::SyncAC3(uint8_t* data, unsigned int size)
477 unsigned int skip = 0;
479 for (; size - skip > 7; ++skip, ++data)
481 bool resyncing = (skip != 0);
482 if (TrySyncAC3(data, size - skip, resyncing, false))
483 return skip;
486 // if we get here, the entire packet is invalid and we have lost sync
487 CLog::Log(LOGINFO, "CAEStreamParser::SyncAC3 - AC3 sync lost");
488 m_hasSync = false;
489 return skip;
492 unsigned int CAEStreamParser::SyncDTS(uint8_t* data, unsigned int size)
494 if (size < 13)
496 if (m_needBytes < 13)
497 m_needBytes = 14;
498 return 0;
501 unsigned int skip = 0;
502 for (; size - skip > 13; ++skip, ++data)
504 unsigned int header = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
505 unsigned int hd_sync = 0;
506 unsigned int dtsBlocks;
507 unsigned int amode;
508 unsigned int sfreq;
509 unsigned int target_rate;
510 unsigned int extension = 0;
511 unsigned int ext_type = UNKNOWN_DTS_EXTENSION;
512 unsigned int lfe;
513 int bits;
515 switch (header)
517 // 14bit BE
518 case DTS_PREAMBLE_14BE:
519 if (data[4] != 0x07 || (data[5] & 0xf0) != 0xf0)
520 continue;
521 dtsBlocks = (((data[5] & 0x7) << 4) | ((data[6] & 0x3C) >> 2)) + 1;
522 m_fsize = (((((data[6] & 0x3) << 8) | data[7]) << 4) | ((data[8] & 0x3C) >> 2)) + 1;
523 amode = ((data[8] & 0x3) << 4) | ((data[9] & 0xF0) >> 4);
524 target_rate = ((data[10] & 0x3e) >> 1);
525 extension = ((data[11] & 0x1));
526 ext_type = ((data[11] & 0xe) >> 1);
527 sfreq = data[9] & 0xF;
528 lfe = (data[12] & 0x18) >> 3;
529 m_info.m_dataIsLE = false;
530 bits = 14;
531 break;
533 // 14bit LE
534 case DTS_PREAMBLE_14LE:
535 if (data[5] != 0x07 || (data[4] & 0xf0) != 0xf0)
536 continue;
537 dtsBlocks = (((data[4] & 0x7) << 4) | ((data[7] & 0x3C) >> 2)) + 1;
538 m_fsize = (((((data[7] & 0x3) << 8) | data[6]) << 4) | ((data[9] & 0x3C) >> 2)) + 1;
539 amode = ((data[9] & 0x3) << 4) | ((data[8] & 0xF0) >> 4);
540 target_rate = ((data[11] & 0x3e) >> 1);
541 extension = ((data[10] & 0x1));
542 ext_type = ((data[10] & 0xe) >> 1);
543 sfreq = data[8] & 0xF;
544 lfe = (data[13] & 0x18) >> 3;
545 m_info.m_dataIsLE = true;
546 bits = 14;
547 break;
549 // 16bit BE
550 case DTS_PREAMBLE_16BE:
551 dtsBlocks = (((data[4] & 0x1) << 7) | ((data[5] & 0xFC) >> 2)) + 1;
552 m_fsize = (((((data[5] & 0x3) << 8) | data[6]) << 4) | ((data[7] & 0xF0) >> 4)) + 1;
553 amode = ((data[7] & 0x0F) << 2) | ((data[8] & 0xC0) >> 6);
554 sfreq = (data[8] & 0x3C) >> 2;
555 target_rate = ((data[8] & 0x03) << 3) | ((data[9] & 0xe0) >> 5);
556 extension = (data[10] & 0x10) >> 4;
557 ext_type = (data[10] & 0xe0) >> 5;
558 lfe = (data[10] >> 1) & 0x3;
559 m_info.m_dataIsLE = false;
560 bits = 16;
561 break;
563 // 16bit LE
564 case DTS_PREAMBLE_16LE:
565 dtsBlocks = (((data[5] & 0x1) << 7) | ((data[4] & 0xFC) >> 2)) + 1;
566 m_fsize = (((((data[4] & 0x3) << 8) | data[7]) << 4) | ((data[6] & 0xF0) >> 4)) + 1;
567 amode = ((data[6] & 0x0F) << 2) | ((data[9] & 0xC0) >> 6);
568 sfreq = (data[9] & 0x3C) >> 2;
569 target_rate = ((data[9] & 0x03) << 3) | ((data[8] & 0xe0) >> 5);
570 extension = (data[11] & 0x10) >> 4;
571 ext_type = (data[11] & 0xe0) >> 5;
572 lfe = (data[11] >> 1) & 0x3;
573 m_info.m_dataIsLE = true;
574 bits = 16;
575 break;
577 default:
578 continue;
581 if (sfreq == 0 || sfreq >= DTS_SFREQ_COUNT)
582 continue;
584 // make sure the framesize is sane
585 if (m_fsize < 96 || m_fsize > 16384)
586 continue;
588 CAEStreamInfo::DataType dataType{CAEStreamInfo::STREAM_TYPE_NULL};
589 switch (dtsBlocks << 5)
591 case 512:
592 dataType = CAEStreamInfo::STREAM_TYPE_DTS_512;
593 break;
594 case 1024:
595 dataType = CAEStreamInfo::STREAM_TYPE_DTS_1024;
596 break;
597 case 2048:
598 dataType = CAEStreamInfo::STREAM_TYPE_DTS_2048;
599 break;
602 if (dataType == CAEStreamInfo::STREAM_TYPE_NULL)
603 continue;
605 // adjust the fsize for 14 bit streams
606 if (bits == 14)
607 m_fsize = m_fsize / 14 * 16;
609 // we need enough data to check for DTS-HD
610 if (size - skip < m_fsize + 10)
612 // we can assume DTS sync at this point
613 m_syncFunc = &CAEStreamParser::SyncDTS;
614 m_needBytes = m_fsize + 10;
615 m_fsize = 0;
617 return skip;
620 // look for DTS-HD
621 hd_sync = (data[m_fsize] << 24) | (data[m_fsize + 1] << 16) | (data[m_fsize + 2] << 8) |
622 data[m_fsize + 3];
623 if (hd_sync == DTS_PREAMBLE_HD)
625 int hd_size;
626 bool blownup = (data[m_fsize + 5] & 0x20) != 0;
627 if (blownup)
628 hd_size = (((data[m_fsize + 6] & 0x01) << 19) | (data[m_fsize + 7] << 11) |
629 (data[m_fsize + 8] << 3) | ((data[m_fsize + 9] & 0xe0) >> 5)) +
631 else
632 hd_size = (((data[m_fsize + 6] & 0x1f) << 11) | (data[m_fsize + 7] << 3) |
633 ((data[m_fsize + 8] & 0xe0) >> 5)) +
636 int header_size;
637 if (blownup)
638 header_size = (((data[m_fsize + 5] & 0x1f) << 7) | ((data[m_fsize + 6] & 0xfe) >> 1)) + 1;
639 else
640 header_size = (((data[m_fsize + 5] & 0x1f) << 3) | ((data[m_fsize + 6] & 0xe0) >> 5)) + 1;
642 hd_sync = data[m_fsize + header_size] << 24 | data[m_fsize + header_size + 1] << 16 |
643 data[m_fsize + header_size + 2] << 8 | data[m_fsize + header_size + 3];
645 // set the type according to core or not
646 if (m_coreOnly)
647 dataType = CAEStreamInfo::STREAM_TYPE_DTSHD_CORE;
648 else if (hd_sync == DTS_PREAMBLE_XLL)
649 dataType = CAEStreamInfo::STREAM_TYPE_DTSHD_MA;
650 else if (hd_sync == DTS_PREAMBLE_XCH || hd_sync == DTS_PREAMBLE_XXCH ||
651 hd_sync == DTS_PREAMBLE_X96K || hd_sync == DTS_PREAMBLE_XBR ||
652 hd_sync == DTS_PREAMBLE_LBR)
653 dataType = CAEStreamInfo::STREAM_TYPE_DTSHD;
654 else
655 dataType = m_info.m_type;
657 m_coreSize = m_fsize;
658 m_fsize += hd_size;
661 unsigned int sampleRate = DTSSampleRates[sfreq];
662 if (!m_hasSync || skip || dataType != m_info.m_type || sampleRate != m_info.m_sampleRate ||
663 dtsBlocks != m_dtsBlocks)
665 m_hasSync = true;
666 m_info.m_type = dataType;
667 m_info.m_sampleRate = sampleRate;
668 m_dtsBlocks = dtsBlocks;
669 m_info.m_channels = DTSChannels[amode] + (lfe ? 1 : 0);
670 m_syncFunc = &CAEStreamParser::SyncDTS;
671 m_info.m_frameSize = m_fsize;
672 m_info.m_repeat = 1;
674 if (dataType == CAEStreamInfo::STREAM_TYPE_DTSHD_MA)
676 m_info.m_channels += 2; // FIXME: this needs to be read out, not sure how to do that yet
677 m_info.m_dtsPeriod = (192000 * (8 >> 1)) * (m_dtsBlocks << 5) / m_info.m_sampleRate;
679 else if (dataType == CAEStreamInfo::STREAM_TYPE_DTSHD)
681 m_info.m_dtsPeriod = (192000 * (2 >> 1)) * (m_dtsBlocks << 5) / m_info.m_sampleRate;
683 else
685 m_info.m_dtsPeriod =
686 (m_info.m_sampleRate * (2 >> 1)) * (m_dtsBlocks << 5) / m_info.m_sampleRate;
689 std::string type;
690 switch (dataType)
692 case CAEStreamInfo::STREAM_TYPE_DTSHD:
693 type = "dtsHD";
694 break;
695 case CAEStreamInfo::STREAM_TYPE_DTSHD_MA:
696 type = "dtsHD MA";
697 break;
698 case CAEStreamInfo::STREAM_TYPE_DTSHD_CORE:
699 type = "dtsHD (core)";
700 break;
701 default:
702 type = "dts";
703 break;
706 if (extension)
708 switch (ext_type)
710 case 0:
711 type += " XCH";
712 break;
713 case 2:
714 type += " X96";
715 break;
716 case 6:
717 type += " XXCH";
718 break;
719 default:
720 type += " ext unknown";
721 break;
725 CLog::Log(LOGINFO,
726 "CAEStreamParser::SyncDTS - {} stream detected ({} channels, {}Hz, {}bit {}, "
727 "period: {}, syncword: 0x{:x}, target rate: 0x{:x}, framesize {}))",
728 type, m_info.m_channels, m_info.m_sampleRate, bits, m_info.m_dataIsLE ? "LE" : "BE",
729 m_info.m_dtsPeriod, hd_sync, target_rate, m_fsize);
732 return skip;
735 // lost sync
736 CLog::Log(LOGINFO, "CAEStreamParser::SyncDTS - DTS sync lost");
737 m_hasSync = false;
738 return skip;
741 inline unsigned int CAEStreamParser::GetTrueHDChannels(const uint16_t chanmap)
743 int channels = 0;
744 for (int i = 0; i < 13; ++i)
745 channels += THDChanMap[i] * ((chanmap >> i) & 1);
746 return channels;
749 unsigned int CAEStreamParser::SyncTrueHD(uint8_t* data, unsigned int size)
751 unsigned int left = size;
752 unsigned int skip = 0;
754 // if MLP
755 for (; left; ++skip, ++data, --left)
757 // if we dont have sync and there is less the 8 bytes, then break out
758 if (!m_hasSync && left < 8)
759 return size;
761 // if its a major audio unit
762 uint16_t length = ((data[0] & 0x0F) << 8 | data[1]) << 1;
763 uint32_t syncword = ((((data[4] << 8 | data[5]) << 8) | data[6]) << 8) | data[7];
764 if (syncword == 0xf8726fba)
766 // we need 32 bytes to sync on a master audio unit
767 if (left < 32)
768 return skip;
770 // get the rate and ensure its valid
771 int rate = (data[8] & 0xf0) >> 4;
772 if (rate == 0xF)
773 continue;
775 unsigned int major_sync_size = 28;
776 if (data[29] & 1)
778 // extension(s) present, look up count
779 int extension_count = data[30] >> 4;
780 major_sync_size += 2 + extension_count * 2;
783 if (left < 4 + major_sync_size)
784 return skip;
786 // verify the crc of the audio unit
787 uint16_t crc = av_crc(m_crcTrueHD, 0, data + 4, major_sync_size - 4);
788 crc ^= (data[4 + major_sync_size - 3] << 8) | data[4 + major_sync_size - 4];
789 if (((data[4 + major_sync_size - 1] << 8) | data[4 + major_sync_size - 2]) != crc)
790 continue;
792 // get the sample rate and substreams, we have a valid master audio unit
793 m_info.m_sampleRate = (rate & 0x8 ? 44100 : 48000) << (rate & 0x7);
794 m_substreams = (data[20] & 0xF0) >> 4;
796 // get the number of encoded channels
797 uint16_t channel_map = ((data[10] & 0x1F) << 8) | data[11];
798 if (!channel_map)
799 channel_map = (data[9] << 1) | (data[10] >> 7);
800 m_info.m_channels = CAEStreamParser::GetTrueHDChannels(channel_map);
802 if (!m_hasSync)
803 CLog::Log(LOGINFO,
804 "CAEStreamParser::SyncTrueHD - TrueHD stream detected ({} channels, {}Hz)",
805 m_info.m_channels, m_info.m_sampleRate);
807 m_hasSync = true;
808 m_fsize = length;
809 m_info.m_type = CAEStreamInfo::STREAM_TYPE_TRUEHD;
810 m_syncFunc = &CAEStreamParser::SyncTrueHD;
811 m_info.m_frameSize = length;
812 m_info.m_repeat = 1;
813 return skip;
815 else
817 // we cant sink to a subframe until we have the information from a master audio unit
818 if (!m_hasSync)
819 continue;
821 // if there is not enough data left to verify the packet, just return the skip amount
822 if (left < (unsigned int)m_substreams * 4)
823 return skip;
825 // verify the parity
826 int p = 0;
827 uint8_t check = 0;
828 for (int i = -1; i < m_substreams; ++i)
830 check ^= data[p++];
831 check ^= data[p++];
832 if (i == -1 || data[p - 2] & 0x80)
834 check ^= data[p++];
835 check ^= data[p++];
839 // if the parity nibble does not match
840 if ((((check >> 4) ^ check) & 0xF) != 0xF)
842 // lost sync
843 m_hasSync = false;
844 CLog::Log(LOGINFO, "CAEStreamParser::SyncTrueHD - Sync Lost");
845 continue;
847 else
849 m_fsize = length;
850 return skip;
855 // lost sync
856 m_hasSync = false;
857 return skip;