SoftVideoDecoderOMXComponent.cpp revision db43b34c3428e480f8c4c66e7e88f4001f37f91e
1/*
2 * Copyright (C) 2013 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
17#include <inttypes.h>
18
19//#define LOG_NDEBUG 0
20#define LOG_TAG "SoftVideoDecoderOMXComponent"
21#include <utils/Log.h>
22
23#include "include/SoftVideoDecoderOMXComponent.h"
24
25#include <media/stagefright/foundation/ADebug.h>
26#include <media/stagefright/foundation/ALooper.h>
27#include <media/stagefright/foundation/AMessage.h>
28#include <media/stagefright/MediaDefs.h>
29
30namespace android {
31
32template<class T>
33static void InitOMXParams(T *params) {
34    params->nSize = sizeof(T);
35    params->nVersion.s.nVersionMajor = 1;
36    params->nVersion.s.nVersionMinor = 0;
37    params->nVersion.s.nRevision = 0;
38    params->nVersion.s.nStep = 0;
39}
40
41SoftVideoDecoderOMXComponent::SoftVideoDecoderOMXComponent(
42        const char *name,
43        const char *componentRole,
44        OMX_VIDEO_CODINGTYPE codingType,
45        const CodecProfileLevel *profileLevels,
46        size_t numProfileLevels,
47        int32_t width,
48        int32_t height,
49        const OMX_CALLBACKTYPE *callbacks,
50        OMX_PTR appData,
51        OMX_COMPONENTTYPE **component)
52        : SimpleSoftOMXComponent(name, callbacks, appData, component),
53        mWidth(width),
54        mHeight(height),
55        mCropLeft(0),
56        mCropTop(0),
57        mCropWidth(width),
58        mCropHeight(height),
59        mOutputPortSettingsChange(NONE),
60        mComponentRole(componentRole),
61        mCodingType(codingType),
62        mProfileLevels(profileLevels),
63        mNumProfileLevels(numProfileLevels) {
64}
65
66void SoftVideoDecoderOMXComponent::initPorts(
67        OMX_U32 numInputBuffers,
68        OMX_U32 inputBufferSize,
69        OMX_U32 numOutputBuffers,
70        const char *mimeType) {
71    OMX_PARAM_PORTDEFINITIONTYPE def;
72    InitOMXParams(&def);
73
74    def.nPortIndex = kInputPortIndex;
75    def.eDir = OMX_DirInput;
76    def.nBufferCountMin = numInputBuffers;
77    def.nBufferCountActual = def.nBufferCountMin;
78    def.nBufferSize = inputBufferSize;
79    def.bEnabled = OMX_TRUE;
80    def.bPopulated = OMX_FALSE;
81    def.eDomain = OMX_PortDomainVideo;
82    def.bBuffersContiguous = OMX_FALSE;
83    def.nBufferAlignment = 1;
84
85    def.format.video.cMIMEType = const_cast<char *>(mimeType);
86    def.format.video.pNativeRender = NULL;
87    /* size is initialized in updatePortDefinitions() */
88    def.format.video.nBitrate = 0;
89    def.format.video.xFramerate = 0;
90    def.format.video.bFlagErrorConcealment = OMX_FALSE;
91    def.format.video.eCompressionFormat = mCodingType;
92    def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
93    def.format.video.pNativeWindow = NULL;
94
95    addPort(def);
96
97    def.nPortIndex = kOutputPortIndex;
98    def.eDir = OMX_DirOutput;
99    def.nBufferCountMin = numOutputBuffers;
100    def.nBufferCountActual = def.nBufferCountMin;
101    def.bEnabled = OMX_TRUE;
102    def.bPopulated = OMX_FALSE;
103    def.eDomain = OMX_PortDomainVideo;
104    def.bBuffersContiguous = OMX_FALSE;
105    def.nBufferAlignment = 2;
106
107    def.format.video.cMIMEType = const_cast<char *>("video/raw");
108    def.format.video.pNativeRender = NULL;
109    /* size is initialized in updatePortDefinitions() */
110    def.format.video.nBitrate = 0;
111    def.format.video.xFramerate = 0;
112    def.format.video.bFlagErrorConcealment = OMX_FALSE;
113    def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
114    def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
115    def.format.video.pNativeWindow = NULL;
116
117    addPort(def);
118
119    updatePortDefinitions();
120}
121
122void SoftVideoDecoderOMXComponent::updatePortDefinitions() {
123    OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
124    def->format.video.nFrameWidth = mWidth;
125    def->format.video.nFrameHeight = mHeight;
126    def->format.video.nStride = def->format.video.nFrameWidth;
127    def->format.video.nSliceHeight = def->format.video.nFrameHeight;
128
129    def = &editPortInfo(kOutputPortIndex)->mDef;
130    def->format.video.nFrameWidth = mWidth;
131    def->format.video.nFrameHeight = mHeight;
132    def->format.video.nStride = def->format.video.nFrameWidth;
133    def->format.video.nSliceHeight = def->format.video.nFrameHeight;
134
135    def->nBufferSize =
136            (def->format.video.nFrameWidth *
137             def->format.video.nFrameHeight * 3) / 2;
138
139    mCropLeft = 0;
140    mCropTop = 0;
141    mCropWidth = mWidth;
142    mCropHeight = mHeight;
143}
144
145OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalGetParameter(
146        OMX_INDEXTYPE index, OMX_PTR params) {
147    switch (index) {
148        case OMX_IndexParamVideoPortFormat:
149        {
150            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
151                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
152
153            if (formatParams->nPortIndex > kMaxPortIndex) {
154                return OMX_ErrorUndefined;
155            }
156
157            if (formatParams->nIndex != 0) {
158                return OMX_ErrorNoMore;
159            }
160
161            if (formatParams->nPortIndex == kInputPortIndex) {
162                formatParams->eCompressionFormat = mCodingType;
163                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
164                formatParams->xFramerate = 0;
165            } else {
166                CHECK_EQ(formatParams->nPortIndex, 1u);
167
168                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
169                formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
170                formatParams->xFramerate = 0;
171            }
172
173            return OMX_ErrorNone;
174        }
175
176        case OMX_IndexParamVideoProfileLevelQuerySupported:
177        {
178            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
179                  (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params;
180
181            if (profileLevel->nPortIndex != kInputPortIndex) {
182                ALOGE("Invalid port index: %" PRIu32, profileLevel->nPortIndex);
183                return OMX_ErrorUnsupportedIndex;
184            }
185
186            if (index >= mNumProfileLevels) {
187                return OMX_ErrorNoMore;
188            }
189
190            profileLevel->eProfile = mProfileLevels[index].mProfile;
191            profileLevel->eLevel   = mProfileLevels[index].mLevel;
192            return OMX_ErrorNone;
193        }
194
195        default:
196            return SimpleSoftOMXComponent::internalGetParameter(index, params);
197    }
198}
199
200OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter(
201        OMX_INDEXTYPE index, const OMX_PTR params) {
202    switch (index) {
203        case OMX_IndexParamStandardComponentRole:
204        {
205            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
206                (const OMX_PARAM_COMPONENTROLETYPE *)params;
207
208            if (strncmp((const char *)roleParams->cRole,
209                        mComponentRole,
210                        OMX_MAX_STRINGNAME_SIZE - 1)) {
211                return OMX_ErrorUndefined;
212            }
213
214            return OMX_ErrorNone;
215        }
216
217        case OMX_IndexParamVideoPortFormat:
218        {
219            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
220                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
221
222            if (formatParams->nPortIndex > kMaxPortIndex) {
223                return OMX_ErrorUndefined;
224            }
225
226            if (formatParams->nIndex != 0) {
227                return OMX_ErrorNoMore;
228            }
229
230            return OMX_ErrorNone;
231        }
232
233        default:
234            return SimpleSoftOMXComponent::internalSetParameter(index, params);
235    }
236}
237
238OMX_ERRORTYPE SoftVideoDecoderOMXComponent::getConfig(
239        OMX_INDEXTYPE index, OMX_PTR params) {
240    switch (index) {
241        case OMX_IndexConfigCommonOutputCrop:
242        {
243            OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)params;
244
245            if (rectParams->nPortIndex != kOutputPortIndex) {
246                return OMX_ErrorUndefined;
247            }
248
249            rectParams->nLeft = mCropLeft;
250            rectParams->nTop = mCropTop;
251            rectParams->nWidth = mCropWidth;
252            rectParams->nHeight = mCropHeight;
253
254            return OMX_ErrorNone;
255        }
256
257        default:
258            return OMX_ErrorUnsupportedIndex;
259    }
260}
261
262void SoftVideoDecoderOMXComponent::onReset() {
263    mOutputPortSettingsChange = NONE;
264}
265
266void SoftVideoDecoderOMXComponent::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
267    if (portIndex != kOutputPortIndex) {
268        return;
269    }
270
271    switch (mOutputPortSettingsChange) {
272        case NONE:
273            break;
274
275        case AWAITING_DISABLED:
276        {
277            CHECK(!enabled);
278            mOutputPortSettingsChange = AWAITING_ENABLED;
279            break;
280        }
281
282        default:
283        {
284            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
285            CHECK(enabled);
286            mOutputPortSettingsChange = NONE;
287            break;
288        }
289    }
290}
291
292}  // namespace android
293