00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "AMRAudioRTPSource.hh"
00022 #include "MultiFramedRTPSource.hh"
00023 #include "BitVector.hh"
00024 #include <string.h>
00025 #include <stdlib.h>
00026
00027
00028
00029
00030
00031
00032 class RawAMRRTPSource: public MultiFramedRTPSource {
00033 public:
00034 static RawAMRRTPSource*
00035 createNew(UsageEnvironment& env,
00036 Groupsock* RTPgs, unsigned char rtpPayloadFormat,
00037 Boolean isWideband, Boolean isOctetAligned,
00038 Boolean isInterleaved, Boolean CRCsArePresent);
00039
00040 Boolean isWideband() const { return fIsWideband; }
00041 unsigned char ILL() const { return fILL; }
00042 unsigned char ILP() const { return fILP; }
00043 unsigned TOCSize() const { return fTOCSize; }
00044 unsigned char* TOC() const { return fTOC; }
00045 unsigned& frameIndex() { return fFrameIndex; }
00046 Boolean& isSynchronized() { return fIsSynchronized; }
00047
00048 private:
00049 RawAMRRTPSource(UsageEnvironment& env, Groupsock* RTPgs,
00050 unsigned char rtpPayloadFormat,
00051 Boolean isWideband, Boolean isOctetAligned,
00052 Boolean isInterleaved, Boolean CRCsArePresent);
00053
00054
00055 virtual ~RawAMRRTPSource();
00056
00057 private:
00058
00059 virtual Boolean hasBeenSynchronizedUsingRTCP();
00060
00061 virtual Boolean processSpecialHeader(BufferedPacket* packet,
00062 unsigned& resultSpecialHeaderSize);
00063 virtual char const* MIMEtype() const;
00064
00065 private:
00066 Boolean fIsWideband, fIsOctetAligned, fIsInterleaved, fCRCsArePresent;
00067 unsigned char fILL, fILP;
00068 unsigned fTOCSize;
00069 unsigned char* fTOC;
00070 unsigned fFrameIndex;
00071 Boolean fIsSynchronized;
00072 };
00073
00074 class AMRDeinterleaver: public AMRAudioSource {
00075 public:
00076 static AMRDeinterleaver*
00077 createNew(UsageEnvironment& env,
00078 Boolean isWideband, unsigned numChannels, unsigned maxInterleaveGroupSize,
00079 RawAMRRTPSource* inputSource);
00080
00081 private:
00082 AMRDeinterleaver(UsageEnvironment& env,
00083 Boolean isWideband, unsigned numChannels,
00084 unsigned maxInterleaveGroupSize, RawAMRRTPSource* inputSource);
00085
00086
00087 virtual ~AMRDeinterleaver();
00088
00089 static void afterGettingFrame(void* clientData, unsigned frameSize,
00090 unsigned numTruncatedBytes,
00091 struct timeval presentationTime,
00092 unsigned durationInMicroseconds);
00093 void afterGettingFrame1(unsigned frameSize, struct timeval presentationTime);
00094
00095 private:
00096
00097 void doGetNextFrame();
00098 virtual void doStopGettingFrames();
00099
00100 private:
00101 RawAMRRTPSource* fInputSource;
00102 class AMRDeinterleavingBuffer* fDeinterleavingBuffer;
00103 Boolean fNeedAFrame;
00104 };
00105
00106
00108
00109 #define MAX_NUM_CHANNELS 20 // far larger than ever expected...
00110 #define MAX_INTERLEAVING_GROUP_SIZE 1000 // far larger than ever expected...
00111
00112 AMRAudioSource*
00113 AMRAudioRTPSource::createNew(UsageEnvironment& env,
00114 Groupsock* RTPgs,
00115 RTPSource*& resultRTPSource,
00116 unsigned char rtpPayloadFormat,
00117 Boolean isWideband,
00118 unsigned numChannels,
00119 Boolean isOctetAligned,
00120 unsigned interleaving,
00121 Boolean robustSortingOrder,
00122 Boolean CRCsArePresent) {
00123
00124 if (robustSortingOrder) {
00125 env << "AMRAudioRTPSource::createNew(): 'Robust sorting order' was specified, but we don't yet support this!\n";
00126 return NULL;
00127 } else if (numChannels > MAX_NUM_CHANNELS) {
00128 env << "AMRAudioRTPSource::createNew(): The \"number of channels\" parameter ("
00129 << numChannels << ") is much too large!\n";
00130 return NULL;
00131 } else if (interleaving > MAX_INTERLEAVING_GROUP_SIZE) {
00132 env << "AMRAudioRTPSource::createNew(): The \"interleaving\" parameter ("
00133 << interleaving << ") is much too large!\n";
00134 return NULL;
00135 }
00136
00137
00138 if (!isOctetAligned) {
00139 if (interleaving > 0 || robustSortingOrder || CRCsArePresent) {
00140 env << "AMRAudioRTPSource::createNew(): 'Bandwidth-efficient mode' was specified, along with interleaving, 'robust sorting order', and/or CRCs, so we assume 'octet-aligned mode' instead.\n";
00141 isOctetAligned = True;
00142 }
00143 }
00144
00145 Boolean isInterleaved;
00146 unsigned maxInterleaveGroupSize;
00147 if (interleaving > 0) {
00148 isInterleaved = True;
00149 maxInterleaveGroupSize = interleaving*numChannels;
00150 } else {
00151 isInterleaved = False;
00152 maxInterleaveGroupSize = numChannels;
00153 }
00154
00155 RawAMRRTPSource* rawRTPSource;
00156 resultRTPSource = rawRTPSource
00157 = RawAMRRTPSource::createNew(env, RTPgs, rtpPayloadFormat,
00158 isWideband, isOctetAligned,
00159 isInterleaved, CRCsArePresent);
00160 if (resultRTPSource == NULL) return NULL;
00161
00162 AMRDeinterleaver* deinterleaver
00163 = AMRDeinterleaver::createNew(env, isWideband, numChannels,
00164 maxInterleaveGroupSize, rawRTPSource);
00165 if (deinterleaver == NULL) {
00166 Medium::close(resultRTPSource);
00167 resultRTPSource = NULL;
00168 }
00169
00170 return deinterleaver;
00171 }
00172
00173
00175
00176
00177
00178 class AMRBufferedPacket: public BufferedPacket {
00179 public:
00180 AMRBufferedPacket(RawAMRRTPSource& ourSource);
00181 virtual ~AMRBufferedPacket();
00182
00183 private:
00184 virtual unsigned nextEnclosedFrameSize(unsigned char*& framePtr,
00185 unsigned dataSize);
00186 private:
00187 RawAMRRTPSource& fOurSource;
00188 };
00189
00190 class AMRBufferedPacketFactory: public BufferedPacketFactory {
00191 private:
00192 virtual BufferedPacket* createNewPacket(MultiFramedRTPSource* ourSource);
00193 };
00194
00195
00197
00198 RawAMRRTPSource*
00199 RawAMRRTPSource::createNew(UsageEnvironment& env, Groupsock* RTPgs,
00200 unsigned char rtpPayloadFormat,
00201 Boolean isWideband, Boolean isOctetAligned,
00202 Boolean isInterleaved, Boolean CRCsArePresent) {
00203 return new RawAMRRTPSource(env, RTPgs, rtpPayloadFormat,
00204 isWideband, isOctetAligned,
00205 isInterleaved, CRCsArePresent);
00206 }
00207
00208 RawAMRRTPSource
00209 ::RawAMRRTPSource(UsageEnvironment& env,
00210 Groupsock* RTPgs, unsigned char rtpPayloadFormat,
00211 Boolean isWideband, Boolean isOctetAligned,
00212 Boolean isInterleaved, Boolean CRCsArePresent)
00213 : MultiFramedRTPSource(env, RTPgs, rtpPayloadFormat,
00214 isWideband ? 16000 : 8000,
00215 new AMRBufferedPacketFactory),
00216 fIsWideband(isWideband), fIsOctetAligned(isOctetAligned),
00217 fIsInterleaved(isInterleaved), fCRCsArePresent(CRCsArePresent),
00218 fILL(0), fILP(0), fTOCSize(0), fTOC(NULL), fFrameIndex(0), fIsSynchronized(False) {
00219 }
00220
00221 RawAMRRTPSource::~RawAMRRTPSource() {
00222 delete[] fTOC;
00223 }
00224
00225 #define FT_SPEECH_LOST 14
00226 #define FT_NO_DATA 15
00227
00228 static void unpackBandwidthEfficientData(BufferedPacket* packet,
00229 Boolean isWideband);
00230
00231 Boolean RawAMRRTPSource
00232 ::processSpecialHeader(BufferedPacket* packet,
00233 unsigned& resultSpecialHeaderSize) {
00234
00235
00236 if (!fIsOctetAligned) unpackBandwidthEfficientData(packet, fIsWideband);
00237
00238 unsigned char* headerStart = packet->data();
00239 unsigned packetSize = packet->dataSize();
00240
00241
00242 if (packetSize < 1) return False;
00243 resultSpecialHeaderSize = 1;
00244
00245 if (fIsInterleaved) {
00246
00247 if (packetSize < 2) return False;
00248
00249
00250 unsigned char const secondByte = headerStart[1];
00251 fILL = (secondByte&0xF0)>>4;
00252 fILP = secondByte&0x0F;
00253 if (fILP > fILL) return False;
00254 ++resultSpecialHeaderSize;
00255 }
00256 #ifdef DEBUG
00257 fprintf(stderr, "packetSize: %d, ILL: %d, ILP: %d\n", packetSize, fILL, fILP);
00258 #endif
00259 fFrameIndex = 0;
00260
00261
00262 unsigned numFramesPresent = 0, numNonEmptyFramesPresent = 0;
00263 unsigned tocStartIndex = resultSpecialHeaderSize;
00264 Boolean F;
00265 do {
00266 if (resultSpecialHeaderSize >= packetSize) return False;
00267 unsigned char const tocByte = headerStart[resultSpecialHeaderSize++];
00268 F = (tocByte&0x80) != 0;
00269 unsigned char const FT = (tocByte&0x78) >> 3;
00270 #ifdef DEBUG
00271 unsigned char Q = (tocByte&0x04)>>2;
00272 fprintf(stderr, "\tTOC entry: F %d, FT %d, Q %d\n", F, FT, Q);
00273 #endif
00274 ++numFramesPresent;
00275 if (FT != FT_SPEECH_LOST && FT != FT_NO_DATA) ++numNonEmptyFramesPresent;
00276 } while (F);
00277 #ifdef DEBUG
00278 fprintf(stderr, "TOC contains %d entries (%d non-empty)\n", numFramesPresent, numNonEmptyFramesPresent);
00279 #endif
00280
00281
00282 if (numFramesPresent > fTOCSize) {
00283 delete[] fTOC;
00284 fTOC = new unsigned char[numFramesPresent];
00285 }
00286 fTOCSize = numFramesPresent;
00287 for (unsigned i = 0; i < fTOCSize; ++i) {
00288 unsigned char const tocByte = headerStart[tocStartIndex + i];
00289 fTOC[i] = tocByte&0x7C;
00290 }
00291
00292 if (fCRCsArePresent) {
00293
00294
00295 resultSpecialHeaderSize += numNonEmptyFramesPresent;
00296 #ifdef DEBUG
00297 fprintf(stderr, "Ignoring %d following CRC bytes\n", numNonEmptyFramesPresent);
00298 #endif
00299 if (resultSpecialHeaderSize > packetSize) return False;
00300 }
00301 #ifdef DEBUG
00302 fprintf(stderr, "Total special header size: %d\n", resultSpecialHeaderSize);
00303 #endif
00304
00305 return True;
00306 }
00307
00308 char const* RawAMRRTPSource::MIMEtype() const {
00309 return fIsWideband ? "audio/AMR-WB" : "audio/AMR";
00310 }
00311
00312 Boolean RawAMRRTPSource::hasBeenSynchronizedUsingRTCP() {
00313 return fIsSynchronized;
00314 }
00315
00316
00318
00319 AMRBufferedPacket::AMRBufferedPacket(RawAMRRTPSource& ourSource)
00320 : fOurSource(ourSource) {
00321 }
00322
00323 AMRBufferedPacket::~AMRBufferedPacket() {
00324 }
00325
00326
00327
00328 #define FT_INVALID 65535
00329 static unsigned short const frameBytesFromFT[16] = {
00330 12, 13, 15, 17,
00331 19, 20, 26, 31,
00332 5, FT_INVALID, FT_INVALID, FT_INVALID,
00333 FT_INVALID, FT_INVALID, FT_INVALID, 0
00334 };
00335 static unsigned short const frameBytesFromFTWideband[16] = {
00336 17, 23, 32, 36,
00337 40, 46, 50, 58,
00338 60, 5, FT_INVALID, FT_INVALID,
00339 FT_INVALID, FT_INVALID, 0, 0
00340 };
00341
00342 unsigned AMRBufferedPacket::
00343 nextEnclosedFrameSize(unsigned char*& framePtr, unsigned dataSize) {
00344 if (dataSize == 0) return 0;
00345
00346
00347
00348 unsigned const tocIndex = fOurSource.frameIndex();
00349 if (tocIndex >= fOurSource.TOCSize()) return 0;
00350
00351 unsigned char const tocByte = fOurSource.TOC()[tocIndex];
00352 unsigned char const FT = (tocByte&0x78) >> 3;
00353
00354 unsigned short frameSize
00355 = fOurSource.isWideband() ? frameBytesFromFTWideband[FT] : frameBytesFromFT[FT];
00356 if (frameSize == FT_INVALID) {
00357
00358 fOurSource.envir() << "AMRBufferedPacket::nextEnclosedFrameSize(): invalid FT: " << FT << "\n";
00359 frameSize = 0;
00360 }
00361 #ifdef DEBUG
00362 fprintf(stderr, "AMRBufferedPacket::nextEnclosedFrameSize(): frame #: %d, FT: %d, isWideband: %d => frameSize: %d (dataSize: %d)\n", tocIndex, FT, fOurSource.isWideband(), frameSize, dataSize);
00363 #endif
00364 ++fOurSource.frameIndex();
00365
00366 if (dataSize < frameSize) return 0;
00367 return frameSize;
00368 }
00369
00370 BufferedPacket* AMRBufferedPacketFactory
00371 ::createNewPacket(MultiFramedRTPSource* ourSource) {
00372 return new AMRBufferedPacket((RawAMRRTPSource&)(*ourSource));
00373 }
00374
00376
00377
00378 #define AMR_MAX_FRAME_SIZE 60
00379
00380 class AMRDeinterleavingBuffer {
00381 public:
00382 AMRDeinterleavingBuffer(unsigned numChannels, unsigned maxInterleaveGroupSize);
00383 virtual ~AMRDeinterleavingBuffer();
00384
00385 void deliverIncomingFrame(unsigned frameSize, RawAMRRTPSource* source,
00386 struct timeval presentationTime);
00387 Boolean retrieveFrame(unsigned char* to, unsigned maxSize,
00388 unsigned& resultFrameSize, unsigned& resultNumTruncatedBytes,
00389 u_int8_t& resultFrameHeader,
00390 struct timeval& resultPresentationTime,
00391 Boolean& resultIsSynchronized);
00392
00393 unsigned char* inputBuffer() { return fInputBuffer; }
00394 unsigned inputBufferSize() const { return AMR_MAX_FRAME_SIZE; }
00395
00396 private:
00397 unsigned char* createNewBuffer();
00398
00399 class FrameDescriptor {
00400 public:
00401 FrameDescriptor();
00402 virtual ~FrameDescriptor();
00403
00404 unsigned frameSize;
00405 unsigned char* frameData;
00406 u_int8_t frameHeader;
00407 struct timeval presentationTime;
00408 Boolean fIsSynchronized;
00409 };
00410
00411 unsigned fNumChannels, fMaxInterleaveGroupSize;
00412 FrameDescriptor* fFrames[2];
00413 unsigned char fIncomingBankId;
00414 unsigned char fIncomingBinMax;
00415 unsigned char fOutgoingBinMax;
00416 unsigned char fNextOutgoingBin;
00417 Boolean fHaveSeenPackets;
00418 u_int16_t fLastPacketSeqNumForGroup;
00419 unsigned char* fInputBuffer;
00420 struct timeval fLastRetrievedPresentationTime;
00421 unsigned fNumSuccessiveSyncedFrames;
00422 unsigned char fILL;
00423 };
00424
00425
00427
00428 AMRDeinterleaver* AMRDeinterleaver
00429 ::createNew(UsageEnvironment& env,
00430 Boolean isWideband, unsigned numChannels, unsigned maxInterleaveGroupSize,
00431 RawAMRRTPSource* inputSource) {
00432 return new AMRDeinterleaver(env, isWideband, numChannels, maxInterleaveGroupSize, inputSource);
00433 }
00434
00435 AMRDeinterleaver::AMRDeinterleaver(UsageEnvironment& env,
00436 Boolean isWideband, unsigned numChannels,
00437 unsigned maxInterleaveGroupSize,
00438 RawAMRRTPSource* inputSource)
00439 : AMRAudioSource(env, isWideband, numChannels),
00440 fInputSource(inputSource), fNeedAFrame(False) {
00441 fDeinterleavingBuffer
00442 = new AMRDeinterleavingBuffer(numChannels, maxInterleaveGroupSize);
00443 }
00444
00445 AMRDeinterleaver::~AMRDeinterleaver() {
00446 delete fDeinterleavingBuffer;
00447 Medium::close(fInputSource);
00448 }
00449
00450 static unsigned const uSecsPerFrame = 20000;
00451
00452 void AMRDeinterleaver::doGetNextFrame() {
00453
00454 if (fDeinterleavingBuffer->retrieveFrame(fTo, fMaxSize,
00455 fFrameSize, fNumTruncatedBytes,
00456 fLastFrameHeader, fPresentationTime,
00457 fInputSource->isSynchronized())) {
00458
00459
00460 fNeedAFrame = False;
00461
00462 fDurationInMicroseconds = uSecsPerFrame;
00463
00464
00465
00466
00467 afterGetting(this);
00468 return;
00469 }
00470
00471
00472 fNeedAFrame = True;
00473 if (!fInputSource->isCurrentlyAwaitingData()) {
00474 fInputSource->getNextFrame(fDeinterleavingBuffer->inputBuffer(),
00475 fDeinterleavingBuffer->inputBufferSize(),
00476 afterGettingFrame, this,
00477 FramedSource::handleClosure, this);
00478 }
00479 }
00480
00481 void AMRDeinterleaver::doStopGettingFrames() {
00482 fNeedAFrame = False;
00483 fInputSource->stopGettingFrames();
00484 }
00485
00486 void AMRDeinterleaver
00487 ::afterGettingFrame(void* clientData, unsigned frameSize,
00488 unsigned ,
00489 struct timeval presentationTime,
00490 unsigned ) {
00491 AMRDeinterleaver* deinterleaver = (AMRDeinterleaver*)clientData;
00492 deinterleaver->afterGettingFrame1(frameSize, presentationTime);
00493 }
00494
00495 void AMRDeinterleaver
00496 ::afterGettingFrame1(unsigned frameSize, struct timeval presentationTime) {
00497 RawAMRRTPSource* source = (RawAMRRTPSource*)fInputSource;
00498
00499
00500 fDeinterleavingBuffer->deliverIncomingFrame(frameSize, source, presentationTime);
00501
00502
00503 if (fNeedAFrame) doGetNextFrame();
00504 }
00505
00506
00508
00509 AMRDeinterleavingBuffer
00510 ::AMRDeinterleavingBuffer(unsigned numChannels, unsigned maxInterleaveGroupSize)
00511 : fNumChannels(numChannels), fMaxInterleaveGroupSize(maxInterleaveGroupSize),
00512 fIncomingBankId(0), fIncomingBinMax(0),
00513 fOutgoingBinMax(0), fNextOutgoingBin(0),
00514 fHaveSeenPackets(False), fNumSuccessiveSyncedFrames(0), fILL(0) {
00515
00516 fFrames[0] = new FrameDescriptor[fMaxInterleaveGroupSize];
00517 fFrames[1] = new FrameDescriptor[fMaxInterleaveGroupSize];
00518 fInputBuffer = createNewBuffer();
00519 }
00520
00521 AMRDeinterleavingBuffer::~AMRDeinterleavingBuffer() {
00522 delete[] fInputBuffer;
00523 delete[] fFrames[0]; delete[] fFrames[1];
00524 }
00525
00526 void AMRDeinterleavingBuffer
00527 ::deliverIncomingFrame(unsigned frameSize, RawAMRRTPSource* source,
00528 struct timeval presentationTime) {
00529 fILL = source->ILL();
00530 unsigned char const ILP = source->ILP();
00531 unsigned frameIndex = source->frameIndex();
00532 unsigned short packetSeqNum = source->curPacketRTPSeqNum();
00533
00534
00535
00536 if (ILP > fILL || frameIndex == 0) {
00537 #ifdef DEBUG
00538 fprintf(stderr, "AMRDeinterleavingBuffer::deliverIncomingFrame() param sanity check failed (%d,%d,%d,%d)\n", frameSize, fILL, ILP, frameIndex);
00539 #endif
00540 source->envir().internalError();
00541 }
00542
00543 --frameIndex;
00544 u_int8_t frameHeader;
00545 if (frameIndex >= source->TOCSize()) {
00546 frameHeader = FT_NO_DATA<<3;
00547 } else {
00548 frameHeader = source->TOC()[frameIndex];
00549 }
00550
00551 unsigned frameBlockIndex = frameIndex/fNumChannels;
00552 unsigned frameWithinFrameBlock = frameIndex%fNumChannels;
00553
00554
00555
00556 unsigned uSecIncrement = frameBlockIndex*(fILL+1)*uSecsPerFrame;
00557 presentationTime.tv_usec += uSecIncrement;
00558 presentationTime.tv_sec += presentationTime.tv_usec/1000000;
00559 presentationTime.tv_usec = presentationTime.tv_usec%1000000;
00560
00561
00562 if (!fHaveSeenPackets
00563 || seqNumLT(fLastPacketSeqNumForGroup, packetSeqNum + frameBlockIndex)) {
00564
00565 #ifdef DEBUG
00566 fprintf(stderr, "AMRDeinterleavingBuffer::deliverIncomingFrame(): new interleave group\n");
00567 #endif
00568 fHaveSeenPackets = True;
00569 fLastPacketSeqNumForGroup = packetSeqNum + fILL - ILP;
00570
00571
00572 fIncomingBankId ^= 1;
00573 unsigned char tmp = fIncomingBinMax;
00574 fIncomingBinMax = fOutgoingBinMax;
00575 fOutgoingBinMax = tmp;
00576 fNextOutgoingBin = 0;
00577 }
00578
00579
00580 unsigned const binNumber
00581 = ((ILP + frameBlockIndex*(fILL+1))*fNumChannels + frameWithinFrameBlock)
00582 % fMaxInterleaveGroupSize;
00583 #ifdef DEBUG
00584 fprintf(stderr, "AMRDeinterleavingBuffer::deliverIncomingFrame(): frameIndex %d (%d,%d) put in bank %d, bin %d (%d): size %d, header 0x%02x, presentationTime %lu.%06ld\n", frameIndex, frameBlockIndex, frameWithinFrameBlock, fIncomingBankId, binNumber, fMaxInterleaveGroupSize, frameSize, frameHeader, presentationTime.tv_sec, presentationTime.tv_usec);
00585 #endif
00586 FrameDescriptor& inBin = fFrames[fIncomingBankId][binNumber];
00587 unsigned char* curBuffer = inBin.frameData;
00588 inBin.frameData = fInputBuffer;
00589 inBin.frameSize = frameSize;
00590 inBin.frameHeader = frameHeader;
00591 inBin.presentationTime = presentationTime;
00592 inBin.fIsSynchronized = ((RTPSource*)source)->RTPSource::hasBeenSynchronizedUsingRTCP();
00593
00594 if (curBuffer == NULL) curBuffer = createNewBuffer();
00595 fInputBuffer = curBuffer;
00596
00597 if (binNumber >= fIncomingBinMax) {
00598 fIncomingBinMax = binNumber + 1;
00599 }
00600 }
00601
00602 Boolean AMRDeinterleavingBuffer
00603 ::retrieveFrame(unsigned char* to, unsigned maxSize,
00604 unsigned& resultFrameSize, unsigned& resultNumTruncatedBytes,
00605 u_int8_t& resultFrameHeader,
00606 struct timeval& resultPresentationTime,
00607 Boolean& resultIsSynchronized) {
00608
00609 if (fNextOutgoingBin >= fOutgoingBinMax) return False;
00610
00611 FrameDescriptor& outBin = fFrames[fIncomingBankId^1][fNextOutgoingBin];
00612 unsigned char* fromPtr = outBin.frameData;
00613 unsigned char fromSize = outBin.frameSize;
00614 outBin.frameSize = 0;
00615 resultIsSynchronized = False;
00616 if (outBin.fIsSynchronized) {
00617
00618
00619 if (++fNumSuccessiveSyncedFrames > fILL) {
00620 resultIsSynchronized = True;
00621 fNumSuccessiveSyncedFrames = fILL+1;
00622 }
00623 } else {
00624 fNumSuccessiveSyncedFrames = 0;
00625 }
00626
00627
00628 if (fromSize == 0) {
00629 resultFrameHeader = FT_NO_DATA<<3;
00630
00631
00632 resultPresentationTime = fLastRetrievedPresentationTime;
00633 resultPresentationTime.tv_usec += uSecsPerFrame;
00634 if (resultPresentationTime.tv_usec >= 1000000) {
00635 ++resultPresentationTime.tv_sec;
00636 resultPresentationTime.tv_usec -= 1000000;
00637 }
00638 } else {
00639
00640 resultFrameHeader = outBin.frameHeader;
00641 resultPresentationTime = outBin.presentationTime;
00642 }
00643
00644 fLastRetrievedPresentationTime = resultPresentationTime;
00645
00646 if (fromSize > maxSize) {
00647 resultNumTruncatedBytes = fromSize - maxSize;
00648 resultFrameSize = maxSize;
00649 } else {
00650 resultNumTruncatedBytes = 0;
00651 resultFrameSize = fromSize;
00652 }
00653 memmove(to, fromPtr, resultFrameSize);
00654 #ifdef DEBUG
00655 fprintf(stderr, "AMRDeinterleavingBuffer::retrieveFrame(): from bank %d, bin %d: size %d, header 0x%02x, presentationTime %lu.%06ld\n", fIncomingBankId^1, fNextOutgoingBin, resultFrameSize, resultFrameHeader, resultPresentationTime.tv_sec, resultPresentationTime.tv_usec);
00656 #endif
00657
00658 ++fNextOutgoingBin;
00659 return True;
00660 }
00661
00662 unsigned char* AMRDeinterleavingBuffer::createNewBuffer() {
00663 return new unsigned char[inputBufferSize()];
00664 }
00665
00666 AMRDeinterleavingBuffer::FrameDescriptor::FrameDescriptor()
00667 : frameSize(0), frameData(NULL) {
00668 }
00669
00670 AMRDeinterleavingBuffer::FrameDescriptor::~FrameDescriptor() {
00671 delete[] frameData;
00672 }
00673
00674
00675 static unsigned short const frameBitsFromFT[16] = {
00676 95, 103, 118, 134,
00677 148, 159, 204, 244,
00678 39, 0, 0, 0,
00679 0, 0, 0, 0
00680 };
00681 static unsigned short const frameBitsFromFTWideband[16] = {
00682 132, 177, 253, 285,
00683 317, 365, 397, 461,
00684 477, 40, 0, 0,
00685 0, 0, 0, 0
00686 };
00687
00688 static void unpackBandwidthEfficientData(BufferedPacket* packet,
00689 Boolean isWideband) {
00690 #ifdef DEBUG
00691 fprintf(stderr, "Unpacking 'bandwidth-efficient' payload (%d bytes):\n", packet->dataSize());
00692 for (unsigned j = 0; j < packet->dataSize(); ++j) {
00693 fprintf(stderr, "%02x:", (packet->data())[j]);
00694 }
00695 fprintf(stderr, "\n");
00696 #endif
00697 BitVector fromBV(packet->data(), 0, 8*packet->dataSize());
00698
00699 unsigned const toBufferSize = 2*packet->dataSize();
00700 unsigned char* toBuffer = new unsigned char[toBufferSize];
00701 unsigned toCount = 0;
00702
00703
00704 unsigned CMR = fromBV.getBits(4);
00705 toBuffer[toCount++] = CMR << 4;
00706
00707
00708 while (1) {
00709 unsigned toc = fromBV.getBits(6);
00710 toBuffer[toCount++] = toc << 2;
00711
00712 if ((toc&0x20) == 0) break;
00713 }
00714
00715
00716 unsigned const tocSize = toCount - 1;
00717 for (unsigned i = 1; i <= tocSize; ++i) {
00718 unsigned char tocByte = toBuffer[i];
00719 unsigned char const FT = (tocByte&0x78) >> 3;
00720 unsigned short frameSizeBits
00721 = isWideband ? frameBitsFromFTWideband[FT] : frameBitsFromFT[FT];
00722 unsigned short frameSizeBytes = (frameSizeBits+7)/8;
00723
00724 shiftBits(&toBuffer[toCount], 0,
00725 packet->data(), fromBV.curBitIndex(),
00726 frameSizeBits
00727 );
00728 #ifdef DEBUG
00729 if (frameSizeBits > fromBV.numBitsRemaining()) {
00730 fprintf(stderr, "\tWarning: Unpacking frame %d of %d: want %d bits, but only %d are available!\n", i, tocSize, frameSizeBits, fromBV.numBitsRemaining());
00731 }
00732 #endif
00733 fromBV.skipBits(frameSizeBits);
00734 toCount += frameSizeBytes;
00735 }
00736
00737 #ifdef DEBUG
00738 if (fromBV.numBitsRemaining() > 7) {
00739 fprintf(stderr, "\tWarning: %d bits remain unused!\n", fromBV.numBitsRemaining());
00740 }
00741 #endif
00742
00743
00744 packet->removePadding(packet->dataSize());
00745 packet->appendData(toBuffer, toCount);
00746 delete[] toBuffer;
00747 }