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