|
MythTV
0.25-pre
|
00001 /********** 00002 This library is free software; you can redistribute it and/or modify it under 00003 the terms of the GNU Lesser General Public License as published by the 00004 Free Software Foundation; either version 2.1 of the License, or (at your 00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.) 00006 00007 This library is distributed in the hope that it will be useful, but WITHOUT 00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00009 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 00010 more details. 00011 00012 You should have received a copy of the GNU Lesser General Public License 00013 along with this library; if not, write to the Free Software Foundation, Inc., 00014 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00015 **********/ 00016 // "liveMedia" 00017 // Copyright (c) 1996-2005 Live Networks, Inc. All rights reserved. 00018 // A filter that breaks up an AC3 audio elementary stream into frames 00019 // Implementation 00020 00021 #include "AC3AudioStreamFramer.hh" 00022 #include "StreamParser.hh" 00023 #include <GroupsockHelper.hh> 00024 00026 00027 class AC3FrameParams { 00028 public: 00029 AC3FrameParams() : samplingFreq(0) {} 00030 // 8-byte header at the start of each frame: 00031 // u_int32_t hdr0, hdr1; 00032 unsigned hdr0, hdr1; 00033 00034 // parameters derived from the headers 00035 unsigned kbps, samplingFreq, frameSize; 00036 00037 void setParamsFromHeader(); 00038 }; 00039 00040 class AC3AudioStreamParser: public StreamParser { 00041 public: 00042 AC3AudioStreamParser(AC3AudioStreamFramer* usingSource, 00043 FramedSource* inputSource); 00044 virtual ~AC3AudioStreamParser(); 00045 00046 public: 00047 Boolean testStreamCode(unsigned char ourStreamCode, 00048 unsigned char* ptr, unsigned size); 00049 // returns True iff the initial stream code is ours 00050 unsigned parseFrame(unsigned& numTruncatedBytes); 00051 // returns the size of the frame that was acquired, or 0 if none was 00052 00053 void registerReadInterest(unsigned char* to, unsigned maxSize); 00054 00055 AC3FrameParams const& currentFrame() const { return fCurrentFrame; } 00056 00057 Boolean haveParsedAFrame() const { return fHaveParsedAFrame; } 00058 void readAndSaveAFrame(); 00059 00060 private: 00061 static void afterGettingSavedFrame(void* clientData, unsigned frameSize, 00062 unsigned numTruncatedBytes, 00063 struct timeval presentationTime, 00064 unsigned durationInMicroseconds); 00065 void afterGettingSavedFrame1(unsigned frameSize); 00066 static void onSavedFrameClosure(void* clientData); 00067 void onSavedFrameClosure1(); 00068 00069 private: 00070 AC3AudioStreamFramer* fUsingSource; 00071 unsigned char* fTo; 00072 unsigned fMaxSize; 00073 00074 Boolean fHaveParsedAFrame; 00075 unsigned char* fSavedFrame; 00076 unsigned fSavedFrameSize; 00077 char fSavedFrameFlag; 00078 00079 // Parameters of the most recently read frame: 00080 AC3FrameParams fCurrentFrame; 00081 }; 00082 00083 00085 00086 AC3AudioStreamFramer::AC3AudioStreamFramer(UsageEnvironment& env, 00087 FramedSource* inputSource, 00088 unsigned char streamCode) 00089 : FramedFilter(env, inputSource), fOurStreamCode(streamCode) { 00090 // Use the current wallclock time as the initial 'presentation time': 00091 gettimeofday(&fNextFramePresentationTime, NULL); 00092 00093 fParser = new AC3AudioStreamParser(this, inputSource); 00094 } 00095 00096 AC3AudioStreamFramer::~AC3AudioStreamFramer() { 00097 delete fParser; 00098 } 00099 00100 AC3AudioStreamFramer* 00101 AC3AudioStreamFramer::createNew(UsageEnvironment& env, 00102 FramedSource* inputSource, 00103 unsigned char streamCode) { 00104 // Need to add source type checking here??? ##### 00105 return new AC3AudioStreamFramer(env, inputSource, streamCode); 00106 } 00107 00108 unsigned AC3AudioStreamFramer::samplingRate() { 00109 if (!fParser->haveParsedAFrame()) { 00110 // Because we haven't yet parsed a frame, we don't yet know the input 00111 // stream's sampling rate. So, we first need to read a frame 00112 // (into a special buffer that we keep around for later use). 00113 fParser->readAndSaveAFrame(); 00114 } 00115 00116 return fParser->currentFrame().samplingFreq; 00117 } 00118 00119 void AC3AudioStreamFramer::flushInput() { 00120 fParser->flushInput(); 00121 } 00122 00123 void AC3AudioStreamFramer::doGetNextFrame() { 00124 fParser->registerReadInterest(fTo, fMaxSize); 00125 parseNextFrame(); 00126 } 00127 00128 #define MILLION 1000000 00129 00130 struct timeval AC3AudioStreamFramer::currentFramePlayTime() const { 00131 AC3FrameParams const& fr = fParser->currentFrame(); 00132 unsigned const numSamples = 1536; 00133 unsigned const freq = fr.samplingFreq; 00134 00135 // result is numSamples/freq 00136 unsigned const uSeconds = (freq == 0) ? 0 00137 : ((numSamples*2*MILLION)/freq + 1)/2; // rounds to nearest integer 00138 00139 struct timeval result; 00140 result.tv_sec = uSeconds/MILLION; 00141 result.tv_usec = uSeconds%MILLION; 00142 return result; 00143 } 00144 00145 void AC3AudioStreamFramer 00146 ::handleNewData(void* clientData, unsigned char* ptr, unsigned size, 00147 struct timeval /*presentationTime*/) { 00148 AC3AudioStreamFramer* framer = (AC3AudioStreamFramer*)clientData; 00149 framer->handleNewData(ptr, size); 00150 } 00151 00152 void AC3AudioStreamFramer 00153 ::handleNewData(unsigned char* ptr, unsigned size) { 00154 if (!fParser->testStreamCode(fOurStreamCode, ptr, size)) { 00155 // This block of data is not for us; try again: 00156 parseNextFrame(); 00157 return; 00158 } 00159 00160 // Now that we know that this data is for us, get the next frame: 00161 parseNextFrame(); 00162 } 00163 00164 void AC3AudioStreamFramer::parseNextFrame() { 00165 unsigned acquiredFrameSize = fParser->parseFrame(fNumTruncatedBytes); 00166 if (acquiredFrameSize > 0) { 00167 // We were able to acquire a frame from the input. 00168 // It has already been copied to the reader's space. 00169 fFrameSize = acquiredFrameSize; 00170 00171 // Also set the presentation time, and increment it for next time, 00172 // based on the length of this frame: 00173 fPresentationTime = fNextFramePresentationTime; 00174 00175 struct timeval framePlayTime = currentFramePlayTime(); 00176 fDurationInMicroseconds = framePlayTime.tv_sec*MILLION + framePlayTime.tv_usec; 00177 fNextFramePresentationTime.tv_usec += framePlayTime.tv_usec; 00178 fNextFramePresentationTime.tv_sec 00179 += framePlayTime.tv_sec + fNextFramePresentationTime.tv_usec/MILLION; 00180 fNextFramePresentationTime.tv_usec %= MILLION; 00181 00182 // Call our own 'after getting' function. Because we're not a 'leaf' 00183 // source, we can call this directly, without risking infinite recursion. 00184 afterGetting(this); 00185 } else { 00186 // We were unable to parse a complete frame from the input, because: 00187 // - we had to read more data from the source stream, or 00188 // - the source stream has ended. 00189 } 00190 } 00191 00192 00194 00195 static int const kbpsTable[] = {32, 40, 48, 56, 64, 80, 96, 112, 00196 128, 160, 192, 224, 256, 320, 384, 448, 00197 512, 576, 640}; 00198 00199 void AC3FrameParams::setParamsFromHeader() { 00200 unsigned char byte4 = hdr1 >> 24; 00201 00202 unsigned char kbpsIndex = (byte4&0x3E) >> 1; 00203 if (kbpsIndex > 18) kbpsIndex = 18; 00204 kbps = kbpsTable[kbpsIndex]; 00205 00206 unsigned char samplingFreqIndex = (byte4&0xC0) >> 6; 00207 switch (samplingFreqIndex) { 00208 case 0: 00209 samplingFreq = 48000; 00210 frameSize = 4*kbps; 00211 break; 00212 case 1: 00213 samplingFreq = 44100; 00214 frameSize = 2*(320*kbps/147 + (byte4&1)); 00215 break; 00216 case 2: 00217 case 3: // not legal? 00218 samplingFreq = 32000; 00219 frameSize = 6*kbps; 00220 } 00221 } 00222 00223 AC3AudioStreamParser 00224 ::AC3AudioStreamParser(AC3AudioStreamFramer* usingSource, 00225 FramedSource* inputSource) 00226 : StreamParser(inputSource, FramedSource::handleClosure, usingSource, 00227 &AC3AudioStreamFramer::handleNewData, usingSource), 00228 fUsingSource(usingSource), fHaveParsedAFrame(False), 00229 fSavedFrame(NULL), fSavedFrameSize(0) { 00230 } 00231 00232 AC3AudioStreamParser::~AC3AudioStreamParser() { 00233 } 00234 00235 void AC3AudioStreamParser::registerReadInterest(unsigned char* to, 00236 unsigned maxSize) { 00237 fTo = to; 00238 fMaxSize = maxSize; 00239 } 00240 00241 Boolean AC3AudioStreamParser 00242 ::testStreamCode(unsigned char ourStreamCode, 00243 unsigned char* ptr, unsigned size) { 00244 if (size < 4) return False; // shouldn't happen 00245 unsigned char streamCode = *ptr; 00246 00247 if (streamCode == ourStreamCode) { 00248 // Remove the first 4 bytes from the stream: 00249 memmove(ptr, ptr + 4, size - 4); 00250 totNumValidBytes() = totNumValidBytes() - 4; 00251 00252 return True; 00253 } else { 00254 // Discard all of the data that was just read: 00255 totNumValidBytes() = totNumValidBytes() - size; 00256 00257 return False; 00258 } 00259 } 00260 00261 unsigned AC3AudioStreamParser::parseFrame(unsigned& numTruncatedBytes) { 00262 if (fSavedFrameSize > 0) { 00263 // We've already read and parsed a frame. Use it instead: 00264 memmove(fTo, fSavedFrame, fSavedFrameSize); 00265 delete[] fSavedFrame; fSavedFrame = NULL; 00266 unsigned frameSize = fSavedFrameSize; 00267 fSavedFrameSize = 0; 00268 return frameSize; 00269 } 00270 00271 try { 00272 saveParserState(); 00273 00274 // We expect an AC3 audio header (first 2 bytes == 0x0B77) at the start: 00275 while (1) { 00276 unsigned next4Bytes = test4Bytes(); 00277 if (next4Bytes>>16 == 0x0B77) break; 00278 skipBytes(1); 00279 saveParserState(); 00280 } 00281 fCurrentFrame.hdr0 = get4Bytes(); 00282 fCurrentFrame.hdr1 = test4Bytes(); 00283 00284 fCurrentFrame.setParamsFromHeader(); 00285 fHaveParsedAFrame = True; 00286 00287 // Copy the frame to the requested destination: 00288 unsigned frameSize = fCurrentFrame.frameSize; 00289 if (frameSize > fMaxSize) { 00290 numTruncatedBytes = frameSize - fMaxSize; 00291 frameSize = fMaxSize; 00292 } else { 00293 numTruncatedBytes = 0; 00294 } 00295 00296 fTo[0] = fCurrentFrame.hdr0 >> 24; 00297 fTo[1] = fCurrentFrame.hdr0 >> 16; 00298 fTo[2] = fCurrentFrame.hdr0 >> 8; 00299 fTo[3] = fCurrentFrame.hdr0; 00300 getBytes(&fTo[4], frameSize-4); 00301 skipBytes(numTruncatedBytes); 00302 00303 return frameSize; 00304 } catch (int /*e*/) { 00305 #ifdef DEBUG 00306 fUsingSource->envir() << "AC3AudioStreamParser::parseFrame() EXCEPTION (This is normal behavior - *not* an error)\n"; 00307 #endif 00308 return 0; // the parsing got interrupted 00309 } 00310 } 00311 00312 void AC3AudioStreamParser::readAndSaveAFrame() { 00313 unsigned const maxAC3FrameSize = 4000; 00314 fSavedFrame = new unsigned char[maxAC3FrameSize]; 00315 fSavedFrameSize = 0; 00316 00317 fSavedFrameFlag = 0; 00318 fUsingSource->getNextFrame(fSavedFrame, maxAC3FrameSize, 00319 afterGettingSavedFrame, this, 00320 onSavedFrameClosure, this); 00321 fUsingSource->envir().taskScheduler().doEventLoop(&fSavedFrameFlag); 00322 } 00323 00324 void AC3AudioStreamParser 00325 ::afterGettingSavedFrame(void* clientData, unsigned frameSize, 00326 unsigned /*numTruncatedBytes*/, 00327 struct timeval /*presentationTime*/, 00328 unsigned /*durationInMicroseconds*/) { 00329 AC3AudioStreamParser* parser = (AC3AudioStreamParser*)clientData; 00330 parser->afterGettingSavedFrame1(frameSize); 00331 } 00332 00333 void AC3AudioStreamParser 00334 ::afterGettingSavedFrame1(unsigned frameSize) { 00335 fSavedFrameSize = frameSize; 00336 fSavedFrameFlag = ~0; 00337 } 00338 00339 void AC3AudioStreamParser::onSavedFrameClosure(void* clientData) { 00340 AC3AudioStreamParser* parser = (AC3AudioStreamParser*)clientData; 00341 parser->onSavedFrameClosure1(); 00342 } 00343 00344 void AC3AudioStreamParser::onSavedFrameClosure1() { 00345 delete[] fSavedFrame; fSavedFrame = NULL; 00346 fSavedFrameSize = 0; 00347 fSavedFrameFlag = ~0; 00348 }
1.7.6.1