diff options
Diffstat (limited to 'pjmedia/src/pjmedia-audiodev/s60_g729_bitstream.h')
-rw-r--r-- | pjmedia/src/pjmedia-audiodev/s60_g729_bitstream.h | 171 |
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 |