1/**********
2This library is free software; you can redistribute it and/or modify it under
3the terms of the GNU Lesser General Public License as published by the
4Free Software Foundation; either version 3 of the License, or (at your
5option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
6
7This library is distributed in the hope that it will be useful, but WITHOUT
8ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
10more details.
11
12You should have received a copy of the GNU Lesser General Public License
13along with this library; if not, write to the Free Software Foundation, Inc.,
1451 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15**********/
16// "liveMedia"
17// Copyright (c) 1996-2020 Live Networks, Inc. All rights reserved.
18// A filter that breaks up an AC3 audio elementary stream into frames
19// Implementation
20
21#include "AC3AudioStreamFramer.hh"
22#include "StreamParser.hh"
23#include <GroupsockHelper.hh>
24
25////////// AC3AudioStreamParser definition //////////
26
27class AC3FrameParams {
28public:
29 AC3FrameParams() : samplingFreq(0) {}
30 // 8-byte header at the start of each frame:
31 // u_int32_t hdr0, hdr1;
32 unsigned hdr0, hdr1;
33
34 // parameters derived from the headers
35 unsigned kbps, samplingFreq, frameSize;
36
37 void setParamsFromHeader();
38};
39
40class AC3AudioStreamParser: public StreamParser {
41public:
42 AC3AudioStreamParser(AC3AudioStreamFramer* usingSource,
43 FramedSource* inputSource);
44 virtual ~AC3AudioStreamParser();
45
46public:
47 void testStreamCode(unsigned char ourStreamCode,
48 unsigned char* ptr, unsigned size);
49 unsigned parseFrame(unsigned& numTruncatedBytes);
50 // returns the size of the frame that was acquired, or 0 if none was
51
52 void registerReadInterest(unsigned char* to, unsigned maxSize);
53
54 AC3FrameParams const& currentFrame() const { return fCurrentFrame; }
55
56 Boolean haveParsedAFrame() const { return fHaveParsedAFrame; }
57 void readAndSaveAFrame();
58
59private:
60 static void afterGettingSavedFrame(void* clientData, unsigned frameSize,
61 unsigned numTruncatedBytes,
62 struct timeval presentationTime,
63 unsigned durationInMicroseconds);
64 void afterGettingSavedFrame1(unsigned frameSize);
65 static void onSavedFrameClosure(void* clientData);
66 void onSavedFrameClosure1();
67
68private:
69 AC3AudioStreamFramer* fUsingSource;
70 unsigned char* fTo;
71 unsigned fMaxSize;
72
73 Boolean fHaveParsedAFrame;
74 unsigned char* fSavedFrame;
75 unsigned fSavedFrameSize;
76 char fSavedFrameFlag;
77
78 // Parameters of the most recently read frame:
79 AC3FrameParams fCurrentFrame;
80};
81
82
83////////// AC3AudioStreamFramer implementation //////////
84
85AC3AudioStreamFramer::AC3AudioStreamFramer(UsageEnvironment& env,
86 FramedSource* inputSource,
87 unsigned char streamCode)
88 : FramedFilter(env, inputSource), fOurStreamCode(streamCode) {
89 // Use the current wallclock time as the initial 'presentation time':
90 gettimeofday(&fNextFramePresentationTime, NULL);
91
92 fParser = new AC3AudioStreamParser(this, inputSource);
93}
94
95AC3AudioStreamFramer::~AC3AudioStreamFramer() {
96 delete fParser;
97}
98
99AC3AudioStreamFramer*
100AC3AudioStreamFramer::createNew(UsageEnvironment& env,
101 FramedSource* inputSource,
102 unsigned char streamCode) {
103 // Need to add source type checking here??? #####
104 return new AC3AudioStreamFramer(env, inputSource, streamCode);
105}
106
107unsigned AC3AudioStreamFramer::samplingRate() {
108 if (!fParser->haveParsedAFrame()) {
109 // Because we haven't yet parsed a frame, we don't yet know the input
110 // stream's sampling rate. So, we first need to read a frame
111 // (into a special buffer that we keep around for later use).
112 fParser->readAndSaveAFrame();
113 }
114
115 return fParser->currentFrame().samplingFreq;
116}
117
118void AC3AudioStreamFramer::flushInput() {
119 fParser->flushInput();
120}
121
122void AC3AudioStreamFramer::doGetNextFrame() {
123 fParser->registerReadInterest(fTo, fMaxSize);
124 parseNextFrame();
125}
126
127#define MILLION 1000000
128
129struct timeval AC3AudioStreamFramer::currentFramePlayTime() const {
130 AC3FrameParams const& fr = fParser->currentFrame();
131 unsigned const numSamples = 1536;
132 unsigned const freq = fr.samplingFreq;
133
134 // result is numSamples/freq
135 unsigned const uSeconds = (freq == 0) ? 0
136 : ((numSamples*2*MILLION)/freq + 1)/2; // rounds to nearest integer
137
138 struct timeval result;
139 result.tv_sec = uSeconds/MILLION;
140 result.tv_usec = uSeconds%MILLION;
141 return result;
142}
143
144void AC3AudioStreamFramer
145::handleNewData(void* clientData, unsigned char* ptr, unsigned size,
146 struct timeval /*presentationTime*/) {
147 AC3AudioStreamFramer* framer = (AC3AudioStreamFramer*)clientData;
148 framer->handleNewData(ptr, size);
149}
150
151void AC3AudioStreamFramer
152::handleNewData(unsigned char* ptr, unsigned size) {
153 fParser->testStreamCode(fOurStreamCode, ptr, size);
154
155 parseNextFrame();
156}
157
158void AC3AudioStreamFramer::parseNextFrame() {
159 unsigned acquiredFrameSize = fParser->parseFrame(fNumTruncatedBytes);
160 if (acquiredFrameSize > 0) {
161 // We were able to acquire a frame from the input.
162 // It has already been copied to the reader's space.
163 fFrameSize = acquiredFrameSize;
164
165 // Also set the presentation time, and increment it for next time,
166 // based on the length of this frame:
167 fPresentationTime = fNextFramePresentationTime;
168
169 struct timeval framePlayTime = currentFramePlayTime();
170 fDurationInMicroseconds = framePlayTime.tv_sec*MILLION + framePlayTime.tv_usec;
171 fNextFramePresentationTime.tv_usec += framePlayTime.tv_usec;
172 fNextFramePresentationTime.tv_sec
173 += framePlayTime.tv_sec + fNextFramePresentationTime.tv_usec/MILLION;
174 fNextFramePresentationTime.tv_usec %= MILLION;
175
176 // Call our own 'after getting' function. Because we're not a 'leaf'
177 // source, we can call this directly, without risking infinite recursion.
178 afterGetting(this);
179 } else {
180 // We were unable to parse a complete frame from the input, because:
181 // - we had to read more data from the source stream, or
182 // - the source stream has ended.
183 }
184}
185
186
187////////// AC3AudioStreamParser implementation //////////
188
189static int const kbpsTable[] = {32, 40, 48, 56, 64, 80, 96, 112,
190 128, 160, 192, 224, 256, 320, 384, 448,
191 512, 576, 640};
192
193void AC3FrameParams::setParamsFromHeader() {
194 unsigned char byte4 = hdr1 >> 24;
195
196 unsigned char kbpsIndex = (byte4&0x3E) >> 1;
197 if (kbpsIndex > 18) kbpsIndex = 18;
198 kbps = kbpsTable[kbpsIndex];
199
200 unsigned char samplingFreqIndex = (byte4&0xC0) >> 6;
201 switch (samplingFreqIndex) {
202 case 0:
203 samplingFreq = 48000;
204 frameSize = 4*kbps;
205 break;
206 case 1:
207 samplingFreq = 44100;
208 frameSize = 2*(320*kbps/147 + (byte4&1));
209 break;
210 case 2:
211 case 3: // not legal?
212 samplingFreq = 32000;
213 frameSize = 6*kbps;
214 }
215}
216
217AC3AudioStreamParser
218::AC3AudioStreamParser(AC3AudioStreamFramer* usingSource,
219 FramedSource* inputSource)
220 : StreamParser(inputSource, FramedSource::handleClosure, usingSource,
221 &AC3AudioStreamFramer::handleNewData, usingSource),
222 fUsingSource(usingSource), fHaveParsedAFrame(False),
223 fSavedFrame(NULL), fSavedFrameSize(0) {
224}
225
226AC3AudioStreamParser::~AC3AudioStreamParser() {
227}
228
229void AC3AudioStreamParser::registerReadInterest(unsigned char* to,
230 unsigned maxSize) {
231 fTo = to;
232 fMaxSize = maxSize;
233}
234
235void AC3AudioStreamParser
236::testStreamCode(unsigned char ourStreamCode,
237 unsigned char* ptr, unsigned size) {
238 if (ourStreamCode == 0) return; // we assume that there's no stream code at the beginning of the data
239
240 if (size < 4) return;
241 unsigned char streamCode = *ptr;
242
243 if (streamCode == ourStreamCode) {
244 // Remove the first 4 bytes from the stream:
245 memmove(ptr, ptr + 4, size - 4);
246 totNumValidBytes() = totNumValidBytes() - 4;
247 } else {
248 // Discard all of the data that was just read:
249 totNumValidBytes() = totNumValidBytes() - size;
250 }
251}
252
253unsigned AC3AudioStreamParser::parseFrame(unsigned& numTruncatedBytes) {
254 if (fSavedFrameSize > 0) {
255 // We've already read and parsed a frame. Use it instead:
256 memmove(fTo, fSavedFrame, fSavedFrameSize);
257 delete[] fSavedFrame; fSavedFrame = NULL;
258 unsigned frameSize = fSavedFrameSize;
259 fSavedFrameSize = 0;
260 return frameSize;
261 }
262
263 try {
264 saveParserState();
265
266 // We expect an AC3 audio header (first 2 bytes == 0x0B77) at the start:
267 while (1) {
268 unsigned next4Bytes = test4Bytes();
269 if (next4Bytes>>16 == 0x0B77) break;
270 skipBytes(1);
271 saveParserState();
272 }
273 fCurrentFrame.hdr0 = get4Bytes();
274 fCurrentFrame.hdr1 = test4Bytes();
275
276 fCurrentFrame.setParamsFromHeader();
277 fHaveParsedAFrame = True;
278
279 // Copy the frame to the requested destination:
280 unsigned frameSize = fCurrentFrame.frameSize;
281 if (frameSize > fMaxSize) {
282 numTruncatedBytes = frameSize - fMaxSize;
283 frameSize = fMaxSize;
284 } else {
285 numTruncatedBytes = 0;
286 }
287
288 fTo[0] = fCurrentFrame.hdr0 >> 24;
289 fTo[1] = fCurrentFrame.hdr0 >> 16;
290 fTo[2] = fCurrentFrame.hdr0 >> 8;
291 fTo[3] = fCurrentFrame.hdr0;
292 getBytes(&fTo[4], frameSize-4);
293 skipBytes(numTruncatedBytes);
294
295 return frameSize;
296 } catch (int /*e*/) {
297#ifdef DEBUG
298 fUsingSource->envir() << "AC3AudioStreamParser::parseFrame() EXCEPTION (This is normal behavior - *not* an error)\n";
299#endif
300 return 0; // the parsing got interrupted
301 }
302}
303
304void AC3AudioStreamParser::readAndSaveAFrame() {
305 unsigned const maxAC3FrameSize = 4000;
306 fSavedFrame = new unsigned char[maxAC3FrameSize];
307 fSavedFrameSize = 0;
308
309 fSavedFrameFlag = 0;
310 fUsingSource->getNextFrame(fSavedFrame, maxAC3FrameSize,
311 afterGettingSavedFrame, this,
312 onSavedFrameClosure, this);
313 fUsingSource->envir().taskScheduler().doEventLoop(&fSavedFrameFlag);
314}
315
316void AC3AudioStreamParser
317::afterGettingSavedFrame(void* clientData, unsigned frameSize,
318 unsigned /*numTruncatedBytes*/,
319 struct timeval /*presentationTime*/,
320 unsigned /*durationInMicroseconds*/) {
321 AC3AudioStreamParser* parser = (AC3AudioStreamParser*)clientData;
322 parser->afterGettingSavedFrame1(frameSize);
323}
324
325void AC3AudioStreamParser
326::afterGettingSavedFrame1(unsigned frameSize) {
327 fSavedFrameSize = frameSize;
328 fSavedFrameFlag = ~0;
329}
330
331void AC3AudioStreamParser::onSavedFrameClosure(void* clientData) {
332 AC3AudioStreamParser* parser = (AC3AudioStreamParser*)clientData;
333 parser->onSavedFrameClosure1();
334}
335
336void AC3AudioStreamParser::onSavedFrameClosure1() {
337 delete[] fSavedFrame; fSavedFrame = NULL;
338 fSavedFrameSize = 0;
339 fSavedFrameFlag = ~0;
340}
341