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