1/*--------------------------------------------------------------------------
2Copyright (c) 2017, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7    * Redistributions of source code must retain the above copyright
8      notice, this list of conditions and the following disclaimer.
9    * Redistributions in binary form must reproduce the above
10      copyright notice, this list of conditions and the following
11      disclaimer in the documentation and/or other materials provided
12      with the distribution.
13    * Neither the name of The Linux Foundation nor the names of its
14      contributors may be used to endorse or promote products derived
15      from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28--------------------------------------------------------------------------*/
29
30void omx_video::init_vendor_extensions(VendorExtensionStore &store) {
31
32    //TODO: add extensions based on Codec, m_platform and/or other capability queries
33
34    ADD_EXTENSION("qti-ext-enc-preprocess-rotate", OMX_IndexConfigCommonRotate, OMX_DirOutput)
35    ADD_PARAM_END("angle", OMX_AndroidVendorValueInt32)
36
37    ADD_EXTENSION("qti-ext-enc-avc-intra-period", OMX_IndexConfigVideoAVCIntraPeriod, OMX_DirOutput)
38    ADD_PARAM    ("n-pframes",    OMX_AndroidVendorValueInt32)
39    ADD_PARAM_END("n-idr-period", OMX_AndroidVendorValueInt32)
40
41    ADD_EXTENSION("qti-ext-enc-error-correction", OMX_IndexParamVideoErrorCorrection, OMX_DirOutput)
42    ADD_PARAM_END("resync-marker-spacing-bits", OMX_AndroidVendorValueInt32)
43
44    ADD_EXTENSION("qti-ext-enc-custom-profile-level", OMX_IndexParamVideoProfileLevelCurrent, OMX_DirOutput)
45    ADD_PARAM    ("profile", OMX_AndroidVendorValueInt32)
46    ADD_PARAM_END("level",   OMX_AndroidVendorValueInt32)
47
48    ADD_EXTENSION("qti-ext-enc-timestamp-source-avtimer", OMX_QTIIndexParamEnableAVTimerTimestamps, OMX_DirInput)
49    ADD_PARAM_END("enable", OMX_AndroidVendorValueInt32)
50}
51
52OMX_ERRORTYPE omx_video::get_vendor_extension_config(
53                OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext) {
54    if (ext->nIndex >= mVendorExtensionStore.size()) {
55        return OMX_ErrorNoMore;
56    }
57
58    const VendorExtension& vExt = mVendorExtensionStore[ext->nIndex];
59    DEBUG_PRINT_LOW("VendorExt: getConfig: index=%u (%s)", ext->nIndex, vExt.name());
60
61    vExt.copyInfoTo(ext);
62    if (ext->nParamSizeUsed < vExt.paramCount()) {
63        // this happens during initial getConfig to query only extension-name and param-count
64        return OMX_ErrorNone;
65    }
66
67    // We now have sufficient params allocated in extension data passed.
68    // Following code is to set the extension-specific data
69
70    bool setStatus = true;
71
72    switch ((OMX_U32)vExt.extensionIndex()) {
73        case OMX_IndexConfigCommonRotate:
74        {
75            setStatus &= vExt.setParamInt32(ext, "angle", m_sConfigFrameRotation.nRotation);
76            break;
77        }
78        case OMX_IndexConfigVideoAVCIntraPeriod:
79        {
80            setStatus &= vExt.setParamInt32(ext, "n-pframes", m_sConfigAVCIDRPeriod.nPFrames);
81            setStatus &= vExt.setParamInt32(ext, "n-idr-period", m_sConfigAVCIDRPeriod.nIDRPeriod);
82            break;
83        }
84        case OMX_IndexParamVideoErrorCorrection:
85        {
86            // "bits" @0
87            setStatus &= vExt.setParamInt32(ext,
88                    "resync-marker-spacing-bits", m_sErrorCorrection.nResynchMarkerSpacing);
89            break;
90        }
91        case OMX_IndexParamVideoProfileLevelCurrent:
92        {
93            setStatus &= vExt.setParamInt32(ext, "profile", m_sParamProfileLevel.eProfile);
94            setStatus &= vExt.setParamInt32(ext, "level", m_sParamProfileLevel.eLevel);
95
96            break;
97        }
98        case OMX_QTIIndexParamEnableAVTimerTimestamps:
99        {
100            setStatus &= vExt.setParamInt32(ext, "enable", m_sParamAVTimerTimestampMode.bEnable);
101            break;
102        }
103        default:
104        {
105            return OMX_ErrorNotImplemented;
106        }
107    }
108    return setStatus ? OMX_ErrorNone : OMX_ErrorUndefined;
109}
110
111OMX_ERRORTYPE omx_video::set_vendor_extension_config(
112                OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *ext) {
113
114    ALOGI("set_vendor_extension_config");
115    if (ext->nIndex >= mVendorExtensionStore.size()) {
116        DEBUG_PRINT_ERROR("unrecognized vendor extension index (%u) max(%u)",
117                ext->nIndex, mVendorExtensionStore.size());
118        return OMX_ErrorBadParameter;
119    }
120
121    const VendorExtension& vExt = mVendorExtensionStore[ext->nIndex];
122    DEBUG_PRINT_LOW("VendorExt: setConfig: index=%u (%s)", ext->nIndex, vExt.name());
123
124    OMX_ERRORTYPE err = OMX_ErrorNone;
125    err = vExt.isConfigValid(ext);
126    if (err != OMX_ErrorNone) {
127        return err;
128    }
129
130    // mark this as set, regardless of set_config succeeding/failing.
131    // App will know by inconsistent values in output-format
132    vExt.set();
133
134    bool valueSet = false;
135    switch ((OMX_U32)vExt.extensionIndex()) {
136        case OMX_IndexConfigCommonRotate:
137        {
138            OMX_CONFIG_ROTATIONTYPE rotationParam;
139            memcpy(&rotationParam, &m_sConfigFrameRotation, sizeof(OMX_CONFIG_ROTATIONTYPE));
140            valueSet |= vExt.readParamInt32(ext, "angle", &rotationParam.nRotation);
141            if (!valueSet) {
142                break;
143            }
144
145            DEBUG_PRINT_HIGH("VENDOR-EXT: set_config: OMX_IndexConfigCommonRotate : %d",
146                    rotationParam.nRotation);
147
148            err = set_config(
149                    NULL, OMX_IndexConfigCommonRotate, &rotationParam);
150            if (err != OMX_ErrorNone) {
151                DEBUG_PRINT_ERROR("set_config: OMX_IndexConfigCommonRotate failed !");
152            }
153            break;
154        }
155        case OMX_IndexConfigVideoAVCIntraPeriod:
156        {
157            OMX_VIDEO_CONFIG_AVCINTRAPERIOD idrConfig;
158            memcpy(&idrConfig, &m_sConfigAVCIDRPeriod, sizeof(OMX_VIDEO_CONFIG_AVCINTRAPERIOD));
159            valueSet |= vExt.readParamInt32(ext, "n-pframes", (OMX_S32 *)&(idrConfig.nPFrames));
160            valueSet |= vExt.readParamInt32(ext, "n-idr-period", (OMX_S32 *)&(idrConfig.nIDRPeriod));
161            if (!valueSet) {
162                break;
163            }
164
165            DEBUG_PRINT_HIGH("VENDOR-EXT: set_config: AVC-intra-period : nP=%d, nIDR=%d",
166                    idrConfig.nPFrames, idrConfig.nIDRPeriod);
167
168            err = set_config(
169                    NULL, OMX_IndexConfigVideoAVCIntraPeriod, &idrConfig);
170            if (err != OMX_ErrorNone) {
171                DEBUG_PRINT_ERROR("set_config: OMX_IndexConfigVideoAVCIntraPeriod failed !");
172            }
173            break;
174        }
175        case OMX_IndexParamVideoErrorCorrection:
176        {
177            OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE ecParam;
178            memcpy(&ecParam, &m_sErrorCorrection, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE));
179            valueSet |= vExt.readParamInt32(ext,
180                    "resync-marker-spacing-bits", (OMX_S32 *)&(ecParam.nResynchMarkerSpacing));
181            if (!valueSet) {
182                break;
183            }
184
185            DEBUG_PRINT_HIGH("VENDOR-EXT: set_config: resync-marker-spacing : %d bits",
186                    ecParam.nResynchMarkerSpacing);
187
188            err = set_parameter(
189                    NULL, OMX_IndexParamVideoErrorCorrection, &ecParam);
190            if (err != OMX_ErrorNone) {
191                DEBUG_PRINT_ERROR("set_config: OMX_IndexParamVideoErrorCorrection failed !");
192            }
193            break;
194        }
195        case OMX_IndexParamVideoProfileLevelCurrent:
196        {
197            OMX_VIDEO_PARAM_PROFILELEVELTYPE profileParam;
198            memcpy(&profileParam, &m_sParamProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE));
199            valueSet |= vExt.readParamInt32(ext, "profile", (OMX_S32 *)&(profileParam.eProfile));
200            valueSet |= vExt.readParamInt32(ext, "level", (OMX_S32 *)&(profileParam.eLevel));
201            if (!valueSet) {
202                break;
203            }
204
205            DEBUG_PRINT_HIGH("VENDOR-EXT: set_config: custom-profile/level : profile=%u level=%u",
206                    (OMX_U32)profileParam.eProfile, (OMX_U32)profileParam.eLevel);
207
208            err = set_parameter(
209                    NULL, OMX_IndexParamVideoProfileLevelCurrent, &profileParam);
210            if (err != OMX_ErrorNone) {
211                DEBUG_PRINT_ERROR("set_config: OMX_IndexParamVideoProfileLevelCurrent failed !");
212            }
213
214            break;
215        }
216        case OMX_QTIIndexParamEnableAVTimerTimestamps:
217        {
218            QOMX_ENABLETYPE avTimerEnableParam;
219            memcpy(&avTimerEnableParam, &m_sParamAVTimerTimestampMode, sizeof(QOMX_ENABLETYPE));
220            valueSet |= vExt.readParamInt32(ext, "enable", (OMX_S32 *)&(avTimerEnableParam.bEnable));
221            if (!valueSet) {
222                break;
223            }
224
225            DEBUG_PRINT_HIGH("VENDOR-EXT: AV-timer timestamp mode enable=%u", avTimerEnableParam.bEnable);
226
227            err = set_parameter(
228                    NULL, (OMX_INDEXTYPE)OMX_QTIIndexParamEnableAVTimerTimestamps, &avTimerEnableParam);
229            if (err != OMX_ErrorNone) {
230                DEBUG_PRINT_ERROR("set_param: OMX_QTIIndexParamEnableAVTimerTimestamps failed !");
231            }
232
233            break;
234        }
235        default:
236        {
237            return OMX_ErrorNotImplemented;
238        }
239    }
240    return err;
241}
242