📄 mp3aduinterleaving.cpp
字号:
/**********This library is free software; you can redistribute it and/or modify it underthe terms of the GNU Lesser General Public License as published by theFree Software Foundation; either version 2.1 of the License, or (at youroption) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License formore details.You should have received a copy of the GNU Lesser General Public Licensealong with this library; if not, write to the Free Software Foundation, Inc.,59 Temple Place, Suite 330, Boston, MA 02111-1307 USA**********/// "liveMedia"// Copyright (c) 1996-2004 Live Networks, Inc. All rights reserved.// Interleaving of MP3 ADUs// Implementation#include "MP3ADUinterleaving.hh"#include "MP3ADUdescriptor.hh"#include <string.h>#ifdef TEST_LOSS#include "GroupsockHelper.hh"#endif////////// Interleaving //////////Interleaving::Interleaving(unsigned cycleSize, unsigned char const* cycleArray) : fCycleSize(cycleSize) { for (unsigned i = 0; i < fCycleSize; ++i) { fInverseCycle[cycleArray[i]] = i; }}Interleaving::~Interleaving() {}////////// MP3ADUinterleaverBase //////////MP3ADUinterleaverBase::MP3ADUinterleaverBase(UsageEnvironment& env, FramedSource* inputSource) : FramedFilter(env, inputSource) {}MP3ADUinterleaverBase::~MP3ADUinterleaverBase() {}FramedSource* MP3ADUinterleaverBase::getInputSource(UsageEnvironment& env, char const* inputSourceName) { FramedSource* inputSource; if (!FramedSource::lookupByName(env, inputSourceName, inputSource)) return NULL; if (strcmp(inputSource->MIMEtype(), "audio/MPA-ROBUST") != 0) { env.setResultMsg(inputSourceName, " is not an MP3 ADU source"); return NULL; } return inputSource;}void MP3ADUinterleaverBase::afterGettingFrame(void* clientData, unsigned numBytesRead, unsigned /*numTruncatedBytes*/, struct timeval presentationTime, unsigned durationInMicroseconds) { MP3ADUinterleaverBase* interleaverBase = (MP3ADUinterleaverBase*)clientData; // Finish up after reading: interleaverBase->afterGettingFrame(numBytesRead, presentationTime, durationInMicroseconds); // Then, continue to deliver an outgoing frame: interleaverBase->doGetNextFrame();}////////// InterleavingFrames (definition) //////////class InterleavingFrames {public: InterleavingFrames(unsigned maxCycleSize); virtual ~InterleavingFrames(); Boolean haveReleaseableFrame(); void getIncomingFrameParams(unsigned char index, unsigned char*& dataPtr, unsigned& bytesAvailable); void getReleasingFrameParams(unsigned char index, unsigned char*& dataPtr, unsigned& bytesInUse, struct timeval& presentationTime, unsigned& durationInMicroseconds); void setFrameParams(unsigned char index, unsigned char icc, unsigned char ii, unsigned frameSize, struct timeval presentationTime, unsigned durationInMicroseconds); unsigned nextIndexToRelease() {return fNextIndexToRelease;} void releaseNext();private: unsigned fMaxCycleSize; unsigned fNextIndexToRelease; class InterleavingFrameDescriptor* fDescriptors;};////////// MP3ADUinterleaver //////////MP3ADUinterleaver::MP3ADUinterleaver(UsageEnvironment& env, Interleaving const& interleaving, FramedSource* inputSource) : MP3ADUinterleaverBase(env, inputSource), fInterleaving(interleaving), fFrames(new InterleavingFrames(interleaving.cycleSize())), fII(0), fICC(0) {}MP3ADUinterleaver::~MP3ADUinterleaver() { delete fFrames;}MP3ADUinterleaver* MP3ADUinterleaver::createNew(UsageEnvironment& env, Interleaving const& interleaving, FramedSource* inputSource) { return new MP3ADUinterleaver(env, interleaving, inputSource);}void MP3ADUinterleaver::doGetNextFrame() { // If there's a frame immediately available, deliver it, otherwise get new // frames from the source until one's available: if (fFrames->haveReleaseableFrame()) { releaseOutgoingFrame(); // Call our own 'after getting' function. Because we're not a 'leaf' // source, we can call this directly, without risking infinite recursion. afterGetting(this); } else { fPositionOfNextIncomingFrame = fInterleaving.lookupInverseCycle(fII); unsigned char* dataPtr; unsigned bytesAvailable; fFrames->getIncomingFrameParams(fPositionOfNextIncomingFrame, dataPtr, bytesAvailable); // Read the next incoming frame (asynchronously) fInputSource->getNextFrame(dataPtr, bytesAvailable, &MP3ADUinterleaverBase::afterGettingFrame, this, handleClosure, this); }}void MP3ADUinterleaver::releaseOutgoingFrame() { unsigned char* fromPtr; fFrames->getReleasingFrameParams(fFrames->nextIndexToRelease(), fromPtr, fFrameSize, fPresentationTime, fDurationInMicroseconds); if (fFrameSize > fMaxSize) { fNumTruncatedBytes = fFrameSize - fMaxSize; fFrameSize = fMaxSize; } memmove(fTo, fromPtr, fFrameSize); fFrames->releaseNext();}void MP3ADUinterleaver::afterGettingFrame(unsigned numBytesRead, struct timeval presentationTime, unsigned durationInMicroseconds) { // Set the (icc,ii) and frame size of the newly-read frame: fFrames->setFrameParams(fPositionOfNextIncomingFrame, fICC, fII, numBytesRead, presentationTime, durationInMicroseconds); // Prepare our counters for the next frame: if (++fII == fInterleaving.cycleSize()) { fII = 0; fICC = (fICC+1)%8; }}////////// DeinterleavingFrames (definition) //////////class DeinterleavingFrames {public: DeinterleavingFrames(); virtual ~DeinterleavingFrames(); Boolean haveReleaseableFrame(); void getIncomingFrameParams(unsigned char*& dataPtr, unsigned& bytesAvailable); void getIncomingFrameParamsAfter(unsigned frameSize, struct timeval presentationTime, unsigned durationInMicroseconds, unsigned char& icc, unsigned char& ii); void getReleasingFrameParams(unsigned char*& dataPtr, unsigned& bytesInUse, struct timeval& presentationTime, unsigned& durationInMicroseconds); void moveIncomingFrameIntoPlace(); void releaseNext(); void startNewCycle();private: unsigned fNextIndexToRelease; Boolean fHaveEndedCycle; unsigned fIIlastSeen; unsigned fMinIndexSeen, fMaxIndexSeen; // actually, max+1 class DeinterleavingFrameDescriptor* fDescriptors;};////////// MP3ADUdeinterleaver //////////MP3ADUdeinterleaver::MP3ADUdeinterleaver(UsageEnvironment& env, FramedSource* inputSource) : MP3ADUinterleaverBase(env, inputSource), fFrames(new DeinterleavingFrames), fIIlastSeen(~0), fICClastSeen(~0) {}MP3ADUdeinterleaver::~MP3ADUdeinterleaver() {}MP3ADUdeinterleaver* MP3ADUdeinterleaver::createNew(UsageEnvironment& env, FramedSource* inputSource) { return new MP3ADUdeinterleaver(env, inputSource);}void MP3ADUdeinterleaver::doGetNextFrame() { // If there's a frame immediately available, deliver it, otherwise get new // frames from the source until one's available: if (fFrames->haveReleaseableFrame()) { releaseOutgoingFrame(); // Call our own 'after getting' function. Because we're not a 'leaf' // source, we can call this directly, without risking infinite recursion. afterGetting(this); } else {#ifdef TEST_LOSS NOTE: This code no longer works, because it uses synchronous reads, which are no longer supported. static unsigned const framesPerPacket = 3; static unsigned const frameCount = 0; static Boolean packetIsLost; while (1) { unsigned packetCount = frameCount/framesPerPacket; if ((frameCount++)%framesPerPacket == 0) { packetIsLost = (our_random()%10 == 0); // simulate 10% packet loss ##### } if (packetIsLost) { // Read and discard the next input frame (that would be part of // a lost packet): unsigned char dummyBuf[2000]; unsigned numBytesRead; struct timeval presentationTime;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -