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