DrcPresModeWrap.cpp revision d4838ed14a169f5981c0adc2edcb24559a913fe6
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 "SoftAAC2_DrcWrapper"
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 64
28
29CDrcPresModeWrapper::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
57CDrcPresModeWrapper::~CDrcPresModeWrapper()
58{
59}
60
61void
62CDrcPresModeWrapper::setDecoderHandle(const HANDLE_AACDECODER handle)
63{
64    mHandleDecoder = handle;
65}
66
67void
68CDrcPresModeWrapper::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
126void
127CDrcPresModeWrapper::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
151void
152CDrcPresModeWrapper::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 -16 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