summaryrefslogtreecommitdiff
path: root/pjmedia/src/pjmedia-audiodev/s60_g729_bitstream.h
blob: ae13bb11330547f348915a7fbbb358226e75f1d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
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