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