1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "DrcPresModeWrap.h"
17 
18 #include <assert.h>
19 
20 #define LOG_TAG "C2SoftAacDrcWrapper"
21 //#define LOG_NDEBUG 0
22 #include <utils/Log.h>
23 
24 //#define DRC_PRES_MODE_WRAP_DEBUG
25 
26 #define GPM_ENCODER_TARGET_LEVEL 64
27 #define MAX_TARGET_LEVEL 40
28 
CDrcPresModeWrapper()29 CDrcPresModeWrapper::CDrcPresModeWrapper()
30 {
31     mDataUpdate = true;
32 
33     /* Data from streamInfo. */
34     /* Initialized to the same values as in the aac decoder */
35     mStreamPRL = -1;
36     mStreamDRCPresMode = -1;
37     mStreamNrAACChan = 0;
38     mStreamNrOutChan = 0;
39 
40     /* Desired values (set by user). */
41     /* Initialized to the same values as in the aac decoder */
42     mDesTarget = -1;
43     mDesAttFactor = 0;
44     mDesBoostFactor = 0;
45     mDesHeavy = 0;
46 
47     mEncoderTarget = -1;
48 
49     /* Values from last time. */
50     /* Initialized to the same values as the desired values */
51     mLastTarget = -1;
52     mLastAttFactor = 0;
53     mLastBoostFactor = 0;
54     mLastHeavy = 0;
55 }
56 
~CDrcPresModeWrapper()57 CDrcPresModeWrapper::~CDrcPresModeWrapper()
58 {
59 }
60 
61 void
setDecoderHandle(const HANDLE_AACDECODER handle)62 CDrcPresModeWrapper::setDecoderHandle(const HANDLE_AACDECODER handle)
63 {
64     mHandleDecoder = handle;
65 }
66 
67 void
submitStreamData(CStreamInfo * pStreamInfo)68 CDrcPresModeWrapper::submitStreamData(CStreamInfo* pStreamInfo)
69 {
70     assert(pStreamInfo);
71 
72     if (mStreamPRL != pStreamInfo->drcProgRefLev) {
73         mStreamPRL = pStreamInfo->drcProgRefLev;
74         mDataUpdate = true;
75 #ifdef DRC_PRES_MODE_WRAP_DEBUG
76         ALOGV("DRC presentation mode wrapper: drcProgRefLev is %d\n", mStreamPRL);
77 #endif
78     }
79 
80     if (mStreamDRCPresMode != pStreamInfo->drcPresMode) {
81         mStreamDRCPresMode = pStreamInfo->drcPresMode;
82         mDataUpdate = true;
83 #ifdef DRC_PRES_MODE_WRAP_DEBUG
84         ALOGV("DRC presentation mode wrapper: drcPresMode is %d\n", mStreamDRCPresMode);
85 #endif
86     }
87 
88     if (mStreamNrAACChan != pStreamInfo->aacNumChannels) {
89         mStreamNrAACChan = pStreamInfo->aacNumChannels;
90         mDataUpdate = true;
91 #ifdef DRC_PRES_MODE_WRAP_DEBUG
92         ALOGV("DRC presentation mode wrapper: aacNumChannels is %d\n", mStreamNrAACChan);
93 #endif
94     }
95 
96     if (mStreamNrOutChan != pStreamInfo->numChannels) {
97         mStreamNrOutChan = pStreamInfo->numChannels;
98         mDataUpdate = true;
99 #ifdef DRC_PRES_MODE_WRAP_DEBUG
100         ALOGV("DRC presentation mode wrapper: numChannels is %d\n", mStreamNrOutChan);
101 #endif
102     }
103 
104 
105 
106     if (mStreamNrOutChan<mStreamNrAACChan) {
107         mIsDownmix = true;
108     } else {
109         mIsDownmix = false;
110     }
111 
112     if (mIsDownmix && (mStreamNrOutChan == 1)) {
113         mIsMonoDownmix = true;
114     } else {
115         mIsMonoDownmix = false;
116     }
117 
118     if (mIsDownmix && mStreamNrOutChan == 2){
119         mIsStereoDownmix = true;
120     } else {
121         mIsStereoDownmix = false;
122     }
123 
124 }
125 
126 void
setParam(const DRC_PRES_MODE_WRAP_PARAM param,const int value)127 CDrcPresModeWrapper::setParam(const DRC_PRES_MODE_WRAP_PARAM param, const int value)
128 {
129     switch (param) {
130     case DRC_PRES_MODE_WRAP_DESIRED_TARGET:
131         mDesTarget = value;
132         break;
133     case DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR:
134         mDesAttFactor = value;
135         break;
136     case DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR:
137         mDesBoostFactor = value;
138         break;
139     case DRC_PRES_MODE_WRAP_DESIRED_HEAVY:
140         mDesHeavy = value;
141         break;
142     case DRC_PRES_MODE_WRAP_ENCODER_TARGET:
143         mEncoderTarget = value;
144         break;
145     default:
146         break;
147     }
148     mDataUpdate = true;
149 }
150 
151 void
update()152 CDrcPresModeWrapper::update()
153 {
154     // Get Data from Decoder
155     int progRefLevel = mStreamPRL;
156     int drcPresMode = mStreamDRCPresMode;
157 
158     // by default, do as desired
159     int newTarget         = mDesTarget;
160     int newAttFactor      = mDesAttFactor;
161     int newBoostFactor    = mDesBoostFactor;
162     int newHeavy          = mDesHeavy;
163 
164     if (mDataUpdate) {
165         // sanity check
166         if (mDesTarget < MAX_TARGET_LEVEL){
167             mDesTarget = MAX_TARGET_LEVEL;  // limit target level to -10 dB or below
168             newTarget = MAX_TARGET_LEVEL;
169         }
170 
171         if (mEncoderTarget != -1) {
172             if (mDesTarget<124) { // if target level > -31 dB
173                 if ((mIsStereoDownmix == false) && (mIsMonoDownmix == false)) {
174                     // no stereo or mono downmixing, calculated scaling of light DRC
175                     /* use as little compression as possible */
176                     newAttFactor = 0;
177                     newBoostFactor = 0;
178                     if (mDesTarget<progRefLevel) { // if target level > PRL
179                         if (mEncoderTarget < mDesTarget) { // if mEncoderTarget > target level
180                             // mEncoderTarget > target level > PRL
181                             int calcFactor;
182                             float calcFactor_norm;
183                             // 0.0f < calcFactor_norm < 1.0f
184                             calcFactor_norm = (float)(mDesTarget - progRefLevel) /
185                                     (float)(mEncoderTarget - progRefLevel);
186                             calcFactor = (int)(calcFactor_norm*127.0f); // 0 <= calcFactor < 127
187                             // calcFactor is the lower limit
188                             newAttFactor = (calcFactor>newAttFactor) ? calcFactor : newAttFactor;
189                             // new AttFactor will be always = calcFactor, as it is set to 0 before.
190                             newBoostFactor = newAttFactor;
191                         } else {
192                             /* target level > mEncoderTarget > PRL */
193                             // newTDLimiterEnable = 1;
194                             // the time domain limiter must always be active in this case.
195                             //     It is assumed that the framework activates it by default
196                             newAttFactor = 127;
197                             newBoostFactor = 127;
198                         }
199                     } else { // target level <= PRL
200                         // no restrictions required
201                         // newAttFactor = newAttFactor;
202                     }
203                 } else { // downmixing
204                     // if target level > -23 dB or mono downmix
205                     if ( (mDesTarget<92) || mIsMonoDownmix ) {
206                         newHeavy = 1;
207                     } else {
208                         // we perform a downmix, so, we need at least full light DRC
209                         newAttFactor = 127;
210                     }
211                 }
212             } else { // target level <= -31 dB
213                 // playback -31 dB: light DRC only needed if we perform downmixing
214                 if (mIsDownmix) {   // we do downmixing
215                     newAttFactor = 127;
216                 }
217             }
218         }
219         else { // handle other used encoder target levels
220 
221             // Sanity check: DRC presentation mode is only specified for max. 5.1 channels
222             if (mStreamNrAACChan > 6) {
223                 drcPresMode = 0;
224             }
225 
226             switch (drcPresMode) {
227             case 0:
228             default: // presentation mode not indicated
229             {
230 
231                 if (mDesTarget<124) { // if target level > -31 dB
232                     // no stereo or mono downmixing
233                     if ((mIsStereoDownmix == false) && (mIsMonoDownmix == false)) {
234                         if (mDesTarget<progRefLevel) { // if target level > PRL
235                             // newTDLimiterEnable = 1;
236                             // the time domain limiter must always be active in this case.
237                             //    It is assumed that the framework activates it by default
238                             newAttFactor = 127; // at least, use light compression
239                         } else { // target level <= PRL
240                             // no restrictions required
241                             // newAttFactor = newAttFactor;
242                         }
243                     } else { // downmixing
244                         // newTDLimiterEnable = 1;
245                         // the time domain limiter must always be active in this case.
246                         //    It is assumed that the framework activates it by default
247 
248                         // if target level > -23 dB or mono downmix
249                         if ( (mDesTarget < 92) || mIsMonoDownmix ) {
250                             newHeavy = 1;
251                         } else{
252                             // we perform a downmix, so, we need at least full light DRC
253                             newAttFactor = 127;
254                         }
255                     }
256                 } else { // target level <= -31 dB
257                     if (mIsDownmix) {   // we do downmixing.
258                         // newTDLimiterEnable = 1;
259                         // the time domain limiter must always be active in this case.
260                         //    It is assumed that the framework activates it by default
261                         newAttFactor = 127;
262                     }
263                 }
264             }
265             break;
266 
267             // Presentation mode 1 and 2 according to ETSI TS 101 154:
268             // Digital Video Broadcasting (DVB); Specification for the use of Video and Audio Coding
269             // in Broadcasting Applications based on the MPEG-2 Transport Stream,
270             // section C.5.4., "Decoding", and Table C.33
271             // ISO DRC            -> newHeavy = 0  (Use light compression, MPEG-style)
272             // Compression_value  -> newHeavy = 1  (Use heavy compression, DVB-style)
273             // scaling restricted -> newAttFactor = 127
274 
275             case 1: // presentation mode 1, Light:-31/Heavy:-23
276             {
277                 if (mDesTarget < 124) { // if target level > -31 dB
278                     // playback up to -23 dB
279                     newHeavy = 1;
280                 } else { // target level <= -31 dB
281                     // playback -31 dB
282                     if (mIsDownmix) {   // we do downmixing.
283                         newAttFactor = 127;
284                     }
285                 }
286             }
287             break;
288 
289             case 2: // presentation mode 2, Light:-23/Heavy:-23
290             {
291                 if (mDesTarget < 124) { // if target level > -31 dB
292                     // playback up to -23 dB
293                     if (mIsMonoDownmix) { // if mono downmix
294                         newHeavy = 1;
295                     } else {
296                         newHeavy = 0;
297                         newAttFactor = 127;
298                     }
299                 } else { // target level <= -31 dB
300                     // playback -31 dB
301                     newHeavy = 0;
302                     if (mIsDownmix) {   // we do downmixing.
303                         newAttFactor = 127;
304                     }
305                 }
306             }
307             break;
308 
309             } // switch()
310         } // if (mEncoderTarget  == GPM_ENCODER_TARGET_LEVEL)
311 
312         // sanity again
313         if (newHeavy == 1) {
314             newBoostFactor=127; // not really needed as the same would be done by the decoder anyway
315             newAttFactor = 127;
316         }
317 
318         // update the decoder
319         if (newTarget != mLastTarget) {
320             aacDecoder_SetParam(mHandleDecoder, AAC_DRC_REFERENCE_LEVEL, newTarget);
321             mLastTarget = newTarget;
322 #ifdef DRC_PRES_MODE_WRAP_DEBUG
323             if (newTarget != mDesTarget)
324                 ALOGV("DRC presentation mode wrapper: forced target level to %d (from %d)\n", newTarget, mDesTarget);
325             else
326                 ALOGV("DRC presentation mode wrapper: set target level to %d\n", newTarget);
327 #endif
328         }
329 
330         if (newAttFactor != mLastAttFactor) {
331             aacDecoder_SetParam(mHandleDecoder, AAC_DRC_ATTENUATION_FACTOR, newAttFactor);
332             mLastAttFactor = newAttFactor;
333 #ifdef DRC_PRES_MODE_WRAP_DEBUG
334             if (newAttFactor != mDesAttFactor)
335                 ALOGV("DRC presentation mode wrapper: forced attenuation factor to %d (from %d)\n", newAttFactor, mDesAttFactor);
336             else
337                 ALOGV("DRC presentation mode wrapper: set attenuation factor to %d\n", newAttFactor);
338 #endif
339         }
340 
341         if (newBoostFactor != mLastBoostFactor) {
342             aacDecoder_SetParam(mHandleDecoder, AAC_DRC_BOOST_FACTOR, newBoostFactor);
343             mLastBoostFactor = newBoostFactor;
344 #ifdef DRC_PRES_MODE_WRAP_DEBUG
345             if (newBoostFactor != mDesBoostFactor)
346                 ALOGV("DRC presentation mode wrapper: forced boost factor to %d (from %d)\n",
347                         newBoostFactor, mDesBoostFactor);
348             else
349                 ALOGV("DRC presentation mode wrapper: set boost factor to %d\n", newBoostFactor);
350 #endif
351         }
352 
353         if (newHeavy != mLastHeavy) {
354             aacDecoder_SetParam(mHandleDecoder, AAC_DRC_HEAVY_COMPRESSION, newHeavy);
355             mLastHeavy = newHeavy;
356 #ifdef DRC_PRES_MODE_WRAP_DEBUG
357             if (newHeavy != mDesHeavy)
358                 ALOGV("DRC presentation mode wrapper: forced heavy compression to %d (from %d)\n",
359                         newHeavy, mDesHeavy);
360             else
361                 ALOGV("DRC presentation mode wrapper: set heavy compression to %d\n", newHeavy);
362 #endif
363         }
364 
365 #ifdef DRC_PRES_MODE_WRAP_DEBUG
366         ALOGV("DRC config: tgt_lev: %3d, cut: %3d, boost: %3d, heavy: %d\n", newTarget,
367                 newAttFactor, newBoostFactor, newHeavy);
368 #endif
369         mDataUpdate = false;
370 
371     } // if (mDataUpdate)
372 }
373