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