1 /***************************************************************************
2 \file ADM_aacadts.cpp
3 \brief wrapper around libavcodec bitstream filter
4 ***************************************************************************/
5
6 /***************************************************************************
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 ***************************************************************************/
14
15 #include <math.h>
16 #include "ADM_default.h"
17 #include "ADM_aacadts.h"
18
19 #if 0
20 #define aprintf printf
21 #else
22 #define aprintf(...) {}
23 #endif
24
25 static const int aacChannels[16]=
26 {
27 0, //0: Defined in AOT Specifc Config
28 1, //1: 1 channel: front-center
29 2, //2: 2 channels: front-left, front-right
30 3, //3: 3 channels: front-center, front-left, front-right
31 4, //4: 4 channels: front-center, front-left, front-right, back-center
32 5, // 5: 5 channels: front-center, front-left, front-right, back-left, back-right
33 6, // 6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
34 8, // 7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel
35 0,0,0,0,
36 0,0,0,0,
37 };
38
39 static uint32_t aacSampleRate[16]=
40 {
41 96000, 88200, 64000, 48000,
42 44100, 32000, 24000, 22050,
43 16000, 12000, 11025, 8000,
44 0, 0, 0, 0
45 };
46
47 /**
48 \fn ctor
49 */
50
ADM_adts2aac(void)51 ADM_adts2aac::ADM_adts2aac(void)
52 {
53 hasExtra=false;
54 extra[0]=extra[1]=0;
55 head=tail=0;
56 buffer.setSize(ADTS_BUFFER_SIZE*2);
57 headOffset=0;
58 }
59 /**
60 \fn dtor
61 */
62
~ADM_adts2aac()63 ADM_adts2aac::~ADM_adts2aac()
64 {
65
66 }
67
68 /**
69 \fn getExtraData
70 \brief extract extradata from adts/aac stream. You must have converted successfully at leat one frame.
71 */
getExtraData(uint32_t * len,uint8_t ** data)72 bool ADM_adts2aac::getExtraData(uint32_t *len,uint8_t **data)
73 {
74 if(hasExtra)
75 {
76 *data=extra;
77 *len=2;
78 return true;
79 }
80 return false;
81 }
82 /**
83 \fn getFrequency
84 \brief get stream frequency. Convert must have been called ok once.
85 */
getFrequency(void)86 int ADM_adts2aac::getFrequency(void)
87 {
88 if(!hasExtra)
89 {
90 ADM_error("No extradata in aac! using default of 48 kHz\n");
91 return 48000;
92 }
93 uint8_t *p=extra;
94 int dex=((p[0]&7)<<1)+(p[1]>>7);
95 return aacSampleRate[dex];
96 }
97 /**
98 \fn getChannels
99 \brief returns # of channels. Convert must have been called ok once.
100 */
getChannels(void)101 int ADM_adts2aac::getChannels(void)
102 {
103 if(!hasExtra)
104 {
105 ADM_error("No extradata in aac! using default of 2 channels\n");
106 return 2;
107 }
108 uint8_t *p=extra;
109 int dex=((p[1]>>3)&0xf);
110 return aacChannels[dex];
111 }
112
113
114 /**
115 \fn addData
116 \brief Add data to our pool
117 */
reset()118 bool ADM_adts2aac::reset()
119 {
120 head=tail=0;
121 hasExtra=false;
122 headOffset=0;
123 return true;
124 }
addData(int incomingLen,const uint8_t * inData)125 bool ADM_adts2aac::addData(int incomingLen,const uint8_t *inData)
126 {
127 // Step 1 : append to our buffer...
128
129 if(head==tail)
130 {
131 headOffset+=tail;
132 head=tail=0;
133 }
134 if(tail>ADTS_BUFFER_SIZE)
135 {
136 headOffset+=tail;
137 int size=head-tail;
138 memmove(buffer.at(0),buffer.at(tail),size);
139 head=size;
140 tail=0;
141
142 }
143 if(head+incomingLen>ADTS_BUFFER_SIZE*2)
144 {
145 ADM_error("Head=%d tail=%d bufferSize=%d\n",head,tail,ADTS_BUFFER_SIZE*2);
146 ADM_error("Adts buffer overflow\n");
147 return false;
148 }
149 memcpy(buffer.at(head),inData,incomingLen);
150 head+=incomingLen;
151 return true;
152 }
153 /**
154 * \fn getAACFrame
155 * \brief try to extract a valid frame from ADTS
156 * @param outLen
157 * @param out
158 * @param offset, offset from the beginning of the stream i.e. 1st add Data
159 * @return
160 */
getAACFrame(int * outLen,uint8_t * out,int * offset)161 ADM_adts2aac::ADTS_STATE ADM_adts2aac::getAACFrame(int *outLen,uint8_t *out,int *offset)
162 {
163 if(outLen)
164 *outLen=0;
165 again:
166 aprintf("[ADTS] *** head=%d tail=%d size=%d***\n",head,tail,head-tail);
167 if(tail+7>head) // we neeed at least 7 bytes...
168 {
169 aprintf("Adts: Not enough data \n");
170 return ADTS_MORE_DATA_NEEDED;
171 }
172 // now search for sync....
173 bool found=false;
174 uint8_t *p=NULL;
175 int packetLen=0;
176 int nbFrames=0;
177 bool crc=false;
178 int match;
179 for( p=(buffer.at(tail));p<(buffer.at(head-6));p++)
180 {
181 if(p[0]!=0xff || (p[1]&0xf0)!=0xf0 || p[1]&6)
182 continue;
183
184 match=p-buffer.at(0); // offset of syncword
185 packetLen=((p[3]&0x3)<<11)+(p[4]<<3)+(p[5]>>5);
186 nbFrames=1+(p[6]&3);
187 if(!(p[1]&1))
188 {
189 crc=true;
190 }
191 if(!packetLen || nbFrames!=1) continue;
192 aprintf("[ADTS] Packet len=%d, nbframes=%d\n",packetLen,nbFrames);
193 aprintf("[ADTS] Found sync at offset %d, buffer size=%d\n",(int)(p-buffer.at(0)),(int)(head-tail));
194 aprintf("[ADTS] Dropping %d bytes\n",(int)(p-buffer.at(0)-tail));
195 if(match==tail && match+packetLen==head)
196 {
197 aprintf("[ADTS] Perfect match\n");
198 found=true;
199 break;
200 }
201 if(match+packetLen+3>head && match+packetLen!=head)
202 {
203 aprintf("[ADTS]** not enough data **\n");
204 return ADTS_MORE_DATA_NEEDED;
205 }
206 // do we have sync at the end ?
207 if(p[packetLen]!=0xff || (p[packetLen+1]&0xf0)!=0xf0 || p[packetLen+1]&6)
208 {
209 aprintf("[ADTS] no syncword at the end or layer!=0\n");
210 continue;
211 }
212 aprintf("[ADTS] End marker found\n");
213 found=true;
214 break;
215
216 }
217 if(found==false)
218 {
219 aprintf("[ADTS]No sync\n");
220 tail=head-6;
221 return ADTS_MORE_DATA_NEEDED;
222 }
223 if(!hasExtra)
224 { // build codec specific info, thanks vlc
225 int i_profile=p[2]>>6;
226 int i_sample_rate_idx=(p[2]>>2)&0x0f;
227 int pi_channels=((p[2]<<2)+((p[3]>>6)))&0x7;
228 extra[0] = (i_profile + 1) << 3 | (i_sample_rate_idx >> 1);
229 extra[1] = ((i_sample_rate_idx & 0x01) << 7) | (pi_channels <<3);
230 hasExtra=true;
231 aprintf("[ADTS] extradata %02x %02x\n",extra[0],extra[1]);
232 }
233 // size ?
234 uint8_t *o;
235 int produced=0;
236 // filter!
237 //-------
238
239 if(crc)
240 {
241 o=p+9;
242 produced=packetLen-9;
243 }else
244 {
245 o=p+7;
246 produced=packetLen-7;
247 }
248 //
249 //---------
250 if(produced<1)
251 {
252 tail=match+1;
253 aprintf("[ADTS] No data produced\n");
254 goto again;
255 }
256 if(offset)
257 {
258 *offset=headOffset+(int)(p-buffer.at(0));
259 }
260 aprintf("[ADTS] Found adts packet of size %d, extradataLen=%d\n",produced,2);
261 if(out)
262 {
263 memcpy(out,o,produced);
264 out+=produced;
265 *outLen+=produced;
266 tail=match+packetLen; // ~ skip
267 }
268 ADM_assert(tail<=head);
269 return ADTS_OK;
270 }
271 /**
272 \fn convert
273 \brief strip adts header. Out can be null if you just want to get headers
274 */
275
convert2(int incomingLen,const uint8_t * inData,int * outLen,uint8_t * out)276 ADM_adts2aac::ADTS_STATE ADM_adts2aac::convert2(int incomingLen,const uint8_t *inData,int *outLen,uint8_t *out)
277 {
278 *outLen=0;
279 bool r=false;
280 if(incomingLen)
281 r=addData(incomingLen,inData);
282 ADTS_STATE state=getAACFrame(outLen,out);
283 if(!r && state==ADTS_MORE_DATA_NEEDED)
284 return ADTS_ERROR;
285 return state;
286 }
287 //EOF
288