1 /*
2  *  Copyright (C) 2005-2021 Team Kodi (https://kodi.tv)
3  *
4  *  SPDX-License-Identifier: GPL-2.0-or-later
5  *  See LICENSE.md for more information.
6  */
7 
8 #include "DSE.h"
9 
10 #include "../BitStream.h"
11 
12 #include <cstring>
13 #include <exception>
14 
15 using namespace aac;
16 using namespace aac::elements;
17 
Decode(BitStream & stream)18 void DSE::Decode(BitStream& stream)
19 {
20   // 4 bits elem id
21   stream.SkipBits(4);
22 
23   const bool byteAlign = stream.ReadBool();
24   int count = stream.ReadBits(8);
25   if (count == 255)
26     count += stream.ReadBits(8);
27 
28   if (byteAlign)
29     stream.ByteAlign();
30 
31   stream.SkipBits(8 * count);
32 }
33 
DecodeRDS(BitStream & stream,uint8_t * & rdsdata)34 uint8_t DSE::DecodeRDS(BitStream& stream, uint8_t*& rdsdata)
35 {
36   // 4 bits elem id
37   stream.SkipBits(4);
38 
39   const bool byteAlign = stream.ReadBool();
40   int count = stream.ReadBits(8);
41   if (count == 255)
42     count += stream.ReadBits(8);
43 
44   if (byteAlign)
45     stream.ByteAlign();
46 
47   static constexpr int BUFFER_SIZE = 65536;
48   static uint8_t buffer[BUFFER_SIZE];
49   static int bufferpos = 0;
50 
51   uint8_t ret = 0;
52 
53   if (count > BUFFER_SIZE)
54   {
55     // data package too large! turn over with next package.
56     stream.SkipBits(8 * count);
57     bufferpos = 0;
58     return ret;
59   }
60 
61   if (bufferpos + count > BUFFER_SIZE)
62   {
63     // buffer overflow! turn over now.
64     bufferpos = 0;
65   }
66 
67   try
68   {
69     // collect data
70     for (int i = 0; i < count; ++i)
71     {
72       buffer[bufferpos + i] = static_cast<uint8_t>(stream.ReadBits(8));
73     }
74     bufferpos += count;
75   }
76   catch (std::exception&)
77   {
78     // cleanup and rethrow
79     bufferpos = 0;
80     throw;
81   }
82 
83   if (bufferpos > 0 && buffer[bufferpos - 1] == 0xFF)
84   {
85     if (buffer[0] == 0xFE)
86     {
87       // data package is complete. deliver it.
88       rdsdata = new uint8_t[bufferpos]; // Note: caller has to delete the data array
89       std::memcpy(rdsdata, buffer, bufferpos);
90       ret = bufferpos;
91     }
92     bufferpos = 0;
93   }
94 
95   return ret;
96 }
97