📄 mp3aduinterleaving.cpp
字号:
// (this works only if the source can be read synchronously) fInputSource->syncGetNextFrame(dummyBuf, sizeof dummyBuf, numBytesRead, presentationTime); } else { break; // from while (1) } }#endif unsigned char* dataPtr; unsigned bytesAvailable; fFrames->getIncomingFrameParams(dataPtr, bytesAvailable); // Read the next incoming frame (asynchronously) fInputSource->getNextFrame(dataPtr, bytesAvailable, &MP3ADUinterleaverBase::afterGettingFrame, this, handleClosure, this); }}void MP3ADUdeinterleaver::afterGettingFrame(unsigned numBytesRead, struct timeval presentationTime, unsigned durationInMicroseconds) { // Get the (icc,ii) and set the frame size of the newly-read frame: unsigned char icc, ii; fFrames->getIncomingFrameParamsAfter(numBytesRead, presentationTime, durationInMicroseconds, icc, ii); // Compare these to the values we saw last: if (icc != fICClastSeen || ii == fIIlastSeen) { // We've started a new interleave cycle // (or interleaving was not used). Release all // pending ADU frames to the ADU->MP3 conversion step: fFrames->startNewCycle(); } else { // We're still in the same cycle as before. // Move the newly-read frame into place, so it can be used: fFrames->moveIncomingFrameIntoPlace(); } fICClastSeen = icc; fIIlastSeen = ii;}void MP3ADUdeinterleaver::releaseOutgoingFrame() { unsigned char* fromPtr; fFrames->getReleasingFrameParams(fromPtr, fFrameSize, fPresentationTime, fDurationInMicroseconds); if (fFrameSize > fMaxSize) { fNumTruncatedBytes = fFrameSize - fMaxSize; fFrameSize = fMaxSize; } memmove(fTo, fromPtr, fFrameSize); fFrames->releaseNext();}////////// InterleavingFrames (implementation) //////////#define MAX_FRAME_SIZE 2000 /* conservatively high */class InterleavingFrameDescriptor {public: InterleavingFrameDescriptor() {frameDataSize = 0;} unsigned frameDataSize; // includes ADU descriptor and (modified) MPEG hdr struct timeval presentationTime; unsigned durationInMicroseconds; unsigned char frameData[MAX_FRAME_SIZE]; // ditto};InterleavingFrames::InterleavingFrames(unsigned maxCycleSize) : fMaxCycleSize(maxCycleSize), fNextIndexToRelease(0), fDescriptors(new InterleavingFrameDescriptor[maxCycleSize]) {}InterleavingFrames::~InterleavingFrames() { delete[] fDescriptors;}Boolean InterleavingFrames::haveReleaseableFrame() { return fDescriptors[fNextIndexToRelease].frameDataSize > 0;}void InterleavingFrames::getIncomingFrameParams(unsigned char index, unsigned char*& dataPtr, unsigned& bytesAvailable) { InterleavingFrameDescriptor& desc = fDescriptors[index]; dataPtr = &desc.frameData[0]; bytesAvailable = MAX_FRAME_SIZE;}void InterleavingFrames::getReleasingFrameParams(unsigned char index, unsigned char*& dataPtr, unsigned& bytesInUse, struct timeval& presentationTime, unsigned& durationInMicroseconds) { InterleavingFrameDescriptor& desc = fDescriptors[index]; dataPtr = &desc.frameData[0]; bytesInUse = desc.frameDataSize; presentationTime = desc.presentationTime; durationInMicroseconds = desc.durationInMicroseconds;}void InterleavingFrames::setFrameParams(unsigned char index, unsigned char icc, unsigned char ii, unsigned frameSize, struct timeval presentationTime, unsigned durationInMicroseconds) { InterleavingFrameDescriptor& desc = fDescriptors[index]; desc.frameDataSize = frameSize; desc.presentationTime = presentationTime; desc.durationInMicroseconds = durationInMicroseconds; // Advance over the ADU descriptor, to get to the MPEG 'syncword': unsigned char* ptr = &desc.frameData[0]; (void)ADUdescriptor::getRemainingFrameSize(ptr); // Replace the next 11 bits with (ii,icc): *ptr++ = ii; *ptr &=~ 0xE0; *ptr |= (icc<<5);}void InterleavingFrames::releaseNext() { fDescriptors[fNextIndexToRelease].frameDataSize = 0; fNextIndexToRelease = (fNextIndexToRelease+1)%fMaxCycleSize;}////////// DeinterleavingFrames (implementation) //////////class DeinterleavingFrameDescriptor {public: DeinterleavingFrameDescriptor() {frameDataSize = 0; frameData = NULL;} virtual ~DeinterleavingFrameDescriptor() {delete[] frameData;} unsigned frameDataSize; // includes ADU descriptor and (modified) MPEG hdr struct timeval presentationTime; unsigned durationInMicroseconds; unsigned char* frameData;};DeinterleavingFrames::DeinterleavingFrames() : fNextIndexToRelease(0), fHaveEndedCycle(False), fMinIndexSeen(MAX_CYCLE_SIZE), fMaxIndexSeen(0), fDescriptors(new DeinterleavingFrameDescriptor[MAX_CYCLE_SIZE+1]) {}DeinterleavingFrames::~DeinterleavingFrames() { delete[] fDescriptors;}Boolean DeinterleavingFrames::haveReleaseableFrame() { if (!fHaveEndedCycle) { // Check just the next frame in the sequence return fDescriptors[fNextIndexToRelease].frameDataSize > 0; } else { // We've just ended a cycle, so we can skip over frames that didn't // get filled in (due to packet loss): if (fNextIndexToRelease < fMinIndexSeen) { fNextIndexToRelease = fMinIndexSeen; } while (fNextIndexToRelease < fMaxIndexSeen && fDescriptors[fNextIndexToRelease].frameDataSize == 0) { ++fNextIndexToRelease; } if (fNextIndexToRelease >= fMaxIndexSeen) { // No more frames are available from the cycle that we just ended, so // clear out all previously stored frames, then make available // the last-read frame, and return false for now: for (unsigned i = fMinIndexSeen; i < fMaxIndexSeen; ++i) { fDescriptors[i].frameDataSize = 0; } fMinIndexSeen = MAX_CYCLE_SIZE; fMaxIndexSeen = 0; moveIncomingFrameIntoPlace(); fHaveEndedCycle = False; fNextIndexToRelease = 0; return False; } return True; }}void DeinterleavingFrames::getIncomingFrameParams(unsigned char*& dataPtr, unsigned& bytesAvailable) { // Use fDescriptors[MAX_CYCLE_SIZE] to store the incoming frame, // prior to figuring out its real position: DeinterleavingFrameDescriptor& desc = fDescriptors[MAX_CYCLE_SIZE]; if (desc.frameData == NULL) { // There's no buffer yet, so allocate a new one: desc.frameData = new unsigned char[MAX_FRAME_SIZE]; } dataPtr = desc.frameData; bytesAvailable = MAX_FRAME_SIZE;}void DeinterleavingFrames::getIncomingFrameParamsAfter(unsigned frameSize, struct timeval presentationTime, unsigned durationInMicroseconds, unsigned char& icc, unsigned char& ii) { DeinterleavingFrameDescriptor& desc = fDescriptors[MAX_CYCLE_SIZE]; desc.frameDataSize = frameSize; desc.presentationTime = presentationTime; desc.durationInMicroseconds = durationInMicroseconds; // Advance over the ADU descriptor, to get to the MPEG 'syncword': unsigned char* ptr = desc.frameData; (void)ADUdescriptor::getRemainingFrameSize(ptr); // Read the next 11 bits into (ii,icc), and replace them with all-1s: fIIlastSeen = ii = *ptr; *ptr++ = 0xFF; icc = (*ptr&0xE0)>>5; *ptr |= 0xE0;}void DeinterleavingFrames::getReleasingFrameParams(unsigned char*& dataPtr, unsigned& bytesInUse, struct timeval& presentationTime, unsigned& durationInMicroseconds) { DeinterleavingFrameDescriptor& desc = fDescriptors[fNextIndexToRelease]; dataPtr = desc.frameData; bytesInUse = desc.frameDataSize; presentationTime = desc.presentationTime; durationInMicroseconds = desc.durationInMicroseconds;}void DeinterleavingFrames::moveIncomingFrameIntoPlace() { DeinterleavingFrameDescriptor& fromDesc = fDescriptors[MAX_CYCLE_SIZE]; DeinterleavingFrameDescriptor& toDesc = fDescriptors[fIIlastSeen]; toDesc.frameDataSize = fromDesc.frameDataSize; toDesc.presentationTime = fromDesc.presentationTime; // Move the data pointer into place by swapping the data pointers: unsigned char* tmp = toDesc.frameData; toDesc.frameData = fromDesc.frameData; fromDesc.frameData = tmp; if (fIIlastSeen < fMinIndexSeen) { fMinIndexSeen = fIIlastSeen; } if (fIIlastSeen + 1 > fMaxIndexSeen) { fMaxIndexSeen = fIIlastSeen + 1; }}void DeinterleavingFrames::releaseNext() { fDescriptors[fNextIndexToRelease].frameDataSize = 0; fNextIndexToRelease = (fNextIndexToRelease+1)%MAX_CYCLE_SIZE;}void DeinterleavingFrames::startNewCycle() { fHaveEndedCycle = True;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -