summaryrefslogtreecommitdiff
path: root/pjmedia/src/pjmedia-audiodev/s60_g729_bitstream.h
diff options
context:
space:
mode:
Diffstat (limited to 'pjmedia/src/pjmedia-audiodev/s60_g729_bitstream.h')
-rw-r--r--pjmedia/src/pjmedia-audiodev/s60_g729_bitstream.h171
1 files changed, 171 insertions, 0 deletions
diff --git a/pjmedia/src/pjmedia-audiodev/s60_g729_bitstream.h b/pjmedia/src/pjmedia-audiodev/s60_g729_bitstream.h
new file mode 100644
index 00000000..ae13bb11
--- /dev/null
+++ b/pjmedia/src/pjmedia-audiodev/s60_g729_bitstream.h
@@ -0,0 +1,171 @@
+#ifndef __BITSTREAM_H_
+#define __BITSTREAM_H_
+
+#define KPackedFrameLen 10
+#define KUnpackedFrameLen 22
+
+// Below values are taken from the APS design document
+const TUint8 KG729FullPayloadBits[] = { 8, 10, 8, 1, 13, 4, 7, 5, 13, 4, 7 };
+const TUint KNumFullFrameParams = 11;
+const TUint8 KG729SIDPayloadBits[] = { 1, 5, 4, 5 };
+const TUint KNumSIDFrameParams = 4;
+
+/*!
+ @class TBitStream
+
+ @discussion Provides compression from 16-bit-word-aligned G.729 audio frames
+ (used in S60 G.729 DSP codec) to 8-bit stream, and vice versa.
+ */
+class TBitStream
+ {
+public:
+ /*!
+ @function TBitStream
+
+ @discussion Constructor
+ */
+ TBitStream():iDes(iData,KUnpackedFrameLen){}
+ /*!
+ @function CompressG729Frame
+
+ @discussion Compress either a 22-byte G.729 full rate frame to 10 bytes
+ or a 8-byte G.729 Annex.B SID frame to 2 bytes.
+ @param aSrc Reference to the uncompressed source frame data
+ @param aIsSIDFrame True if the source is a SID frame
+ @result a reference to the compressed frame
+ */
+ const TDesC8& CompressG729Frame( const TDesC8& aSrc, TBool aIsSIDFrame = EFalse );
+
+ /*!
+ @function ExpandG729Frame
+
+ @discussion Expand a 10-byte G.729 full rate frame to 22 bytes
+ or a 2-byte G.729 Annex.B SID frame to 8(22) bytes.
+ @param aSrc Reference to the compressed source frame data
+ @param aIsSIDFrame True if the source is a SID frame
+ @result a reference to a descriptor representing the uncompressed frame.
+ Note that SID frames are zero-padded to 22 bytes as well.
+ */
+ const TDesC8& ExpandG729Frame( const TDesC8& aSrc, TBool aIsSIDFrame = EFalse );
+
+private:
+ void Compress( TUint8 aValue, TUint8 aNumOfBits );
+ void Expand( const TUint8* aSrc, TInt aDstIdx, TUint8 aNumOfBits );
+
+private:
+ TUint8 iData[KUnpackedFrameLen];
+ TPtr8 iDes;
+ TInt iIdx;
+ TInt iBitOffset;
+ };
+
+
+const TDesC8& TBitStream::CompressG729Frame( const TDesC8& aSrc, TBool aIsSIDFrame )
+ {
+ // reset data
+ iDes.FillZ(iDes.MaxLength());
+ iIdx = iBitOffset = 0;
+
+ TInt numParams = (aIsSIDFrame) ? KNumSIDFrameParams : KNumFullFrameParams;
+ const TUint8* p = const_cast<TUint8*>(aSrc.Ptr());
+
+ for(TInt i = 0, pIdx = 0; i < numParams; i++, pIdx += 2)
+ {
+ TUint8 paramBits = (aIsSIDFrame) ? KG729SIDPayloadBits[i] : KG729FullPayloadBits[i];
+ if(paramBits > 8)
+ {
+ Compress(p[pIdx+1], paramBits - 8); // msb
+ paramBits = 8;
+ }
+ Compress(p[pIdx], paramBits); // lsb
+ }
+
+ if( iBitOffset )
+ iIdx++;
+
+ iDes.SetLength(iIdx);
+ return iDes;
+ }
+
+
+const TDesC8& TBitStream::ExpandG729Frame( const TDesC8& aSrc, TBool aIsSIDFrame )
+ {
+ // reset data
+ iDes.FillZ(iDes.MaxLength());
+ iIdx = iBitOffset = 0;
+
+ TInt numParams = (aIsSIDFrame) ? KNumSIDFrameParams : KNumFullFrameParams;
+ const TUint8* p = const_cast<TUint8*>(aSrc.Ptr());
+
+ for(TInt i = 0, dIdx = 0; i < numParams; i++, dIdx += 2)
+ {
+ TUint8 paramBits = (aIsSIDFrame) ? KG729SIDPayloadBits[i] : KG729FullPayloadBits[i];
+ if(paramBits > 8)
+ {
+ Expand(p, dIdx+1, paramBits - 8); // msb
+ paramBits = 8;
+ }
+ Expand(p, dIdx, paramBits); // lsb
+ }
+
+ iDes.SetLength(KUnpackedFrameLen);
+ return iDes;
+ }
+
+
+void TBitStream::Compress( TUint8 aValue, TUint8 aNumOfBits )
+ {
+ // clear bits that will be discarded
+ aValue &= (0xff >> (8 - aNumOfBits));
+
+ // calculate required bitwise left shift
+ TInt shl = 8 - (iBitOffset + aNumOfBits);
+
+ if (shl == 0) // no shift required
+ {
+ iData[iIdx++] |= aValue;
+ iBitOffset = 0;
+ }
+ else if (shl > 0) // bits fit into current byte
+ {
+ iData[iIdx] |= (aValue << shl);
+ iBitOffset += aNumOfBits;
+ }
+ else
+ {
+ iBitOffset = -shl;
+ iData[iIdx] |= (aValue >> iBitOffset); // right shift
+ iData[++iIdx] |= (aValue << (8-iBitOffset)); // push remaining bits to next byte
+ }
+ }
+
+
+void TBitStream::Expand( const TUint8* aSrc, TInt aDstIdx, TUint8 aNumOfBits )
+ {
+ TUint8 aValue = aSrc[iIdx] & (0xff >> iBitOffset);
+
+ // calculate required bitwise right shift
+ TInt shr = 8 - (iBitOffset + aNumOfBits);
+
+ if (shr == 0) // no shift required
+ {
+ iData[aDstIdx] = aValue;
+ iIdx++;
+ iBitOffset = 0;
+ }
+ else if (shr > 0) // right shift
+ {
+ iData[aDstIdx] = (aValue >> shr);
+ iBitOffset += aNumOfBits;
+ }
+ else // shift left and take remaining bits from the next src byte
+ {
+ iBitOffset = -shr;
+ iData[aDstIdx] = aValue << iBitOffset;
+ iData[aDstIdx] |= aSrc[++iIdx] >> (8 - iBitOffset);
+ }
+ }
+
+#endif // __BITSTREAM_H_
+
+// eof