SoftVideoDecoderOMXComponent.cpp revision fd1e188dc142a8a7adf36e854aa60464faedf0a0
1e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch/*
2e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch * Copyright (C) 2013 The Android Open Source Project
3e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch *
4e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch * Licensed under the Apache License, Version 2.0 (the "License");
5e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch * you may not use this file except in compliance with the License.
6e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch * You may obtain a copy of the License at
7e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch *
8e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch *      http://www.apache.org/licenses/LICENSE-2.0
9e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch *
10e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch * Unless required by applicable law or agreed to in writing, software
11e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch * distributed under the License is distributed on an "AS IS" BASIS,
12e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch * See the License for the specific language governing permissions and
14e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch * limitations under the License.
15e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch */
16e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
17e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include <inttypes.h>
18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
19e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch//#define LOG_NDEBUG 0
20e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#define LOG_TAG "SoftVideoDecoderOMXComponent"
21e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include <utils/Log.h>
22e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
23e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "include/SoftVideoDecoderOMXComponent.h"
24e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
25e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include <media/stagefright/foundation/ADebug.h>
26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include <media/stagefright/foundation/ALooper.h>
27e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include <media/stagefright/foundation/AMessage.h>
28e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include <media/stagefright/MediaDefs.h>
29e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
30e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochnamespace android {
31e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
32e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochtemplate<class T>
33e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochstatic void InitOMXParams(T *params) {
34e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    params->nSize = sizeof(T);
35e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    params->nVersion.s.nVersionMajor = 1;
36e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    params->nVersion.s.nVersionMinor = 0;
37e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    params->nVersion.s.nRevision = 0;
38e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    params->nVersion.s.nStep = 0;
39e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
40e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
41e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochSoftVideoDecoderOMXComponent::SoftVideoDecoderOMXComponent(
42e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        const char *name,
43e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        const char *componentRole,
44e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        OMX_VIDEO_CODINGTYPE codingType,
45e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        const CodecProfileLevel *profileLevels,
46e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        size_t numProfileLevels,
47e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        int32_t width,
48e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        int32_t height,
49e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        const OMX_CALLBACKTYPE *callbacks,
50e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        OMX_PTR appData,
51e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        OMX_COMPONENTTYPE **component)
52e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        : SimpleSoftOMXComponent(name, callbacks, appData, component),
53e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        mWidth(width),
54e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        mHeight(height),
55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        mCropLeft(0),
56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        mCropTop(0),
57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        mCropWidth(width),
58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        mCropHeight(height),
59e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        mOutputPortSettingsChange(NONE),
60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        mComponentRole(componentRole),
61e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        mCodingType(codingType),
62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        mProfileLevels(profileLevels),
63e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        mNumProfileLevels(numProfileLevels) {
64e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
65e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
66e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid SoftVideoDecoderOMXComponent::initPorts(
67e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        OMX_U32 numInputBuffers,
68e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        OMX_U32 inputBufferSize,
69e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        OMX_U32 numOutputBuffers,
70e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        const char *mimeType) {
71e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    OMX_PARAM_PORTDEFINITIONTYPE def;
72e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    InitOMXParams(&def);
73e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
74e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.nPortIndex = kInputPortIndex;
75e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.eDir = OMX_DirInput;
76e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.nBufferCountMin = numInputBuffers;
77e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.nBufferCountActual = def.nBufferCountMin;
78e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.nBufferSize = inputBufferSize;
79e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.bEnabled = OMX_TRUE;
80e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.bPopulated = OMX_FALSE;
81e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.eDomain = OMX_PortDomainVideo;
82e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.bBuffersContiguous = OMX_FALSE;
83e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.nBufferAlignment = 1;
84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.format.video.cMIMEType = const_cast<char *>(mimeType);
86e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.format.video.pNativeRender = NULL;
87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    /* size is initialized in updatePortDefinitions() */
88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.format.video.nBitrate = 0;
89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.format.video.xFramerate = 0;
90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.format.video.bFlagErrorConcealment = OMX_FALSE;
91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.format.video.eCompressionFormat = mCodingType;
92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.format.video.pNativeWindow = NULL;
94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
95e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    addPort(def);
96e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
97e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.nPortIndex = kOutputPortIndex;
98e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.eDir = OMX_DirOutput;
99e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.nBufferCountMin = numOutputBuffers;
100e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.nBufferCountActual = def.nBufferCountMin;
101e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    def.bEnabled = OMX_TRUE;
102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    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            OMX_U32 profileIndex = profileLevel->nProfileIndex;
181
182            if (profileLevel->nPortIndex != kInputPortIndex) {
183                ALOGE("Invalid port index: %" PRIu32, profileLevel->nPortIndex);
184                return OMX_ErrorUnsupportedIndex;
185            }
186
187            if (profileIndex >= mNumProfileLevels) {
188                return OMX_ErrorNoMore;
189            }
190
191            profileLevel->eProfile = mProfileLevels[profileIndex].mProfile;
192            profileLevel->eLevel   = mProfileLevels[profileIndex].mLevel;
193            return OMX_ErrorNone;
194        }
195
196        default:
197            return SimpleSoftOMXComponent::internalGetParameter(index, params);
198    }
199}
200
201OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalSetParameter(
202        OMX_INDEXTYPE index, const OMX_PTR params) {
203    switch (index) {
204        case OMX_IndexParamStandardComponentRole:
205        {
206            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
207                (const OMX_PARAM_COMPONENTROLETYPE *)params;
208
209            if (strncmp((const char *)roleParams->cRole,
210                        mComponentRole,
211                        OMX_MAX_STRINGNAME_SIZE - 1)) {
212                return OMX_ErrorUndefined;
213            }
214
215            return OMX_ErrorNone;
216        }
217
218        case OMX_IndexParamVideoPortFormat:
219        {
220            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
221                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
222
223            if (formatParams->nPortIndex > kMaxPortIndex) {
224                return OMX_ErrorUndefined;
225            }
226
227            if (formatParams->nIndex != 0) {
228                return OMX_ErrorNoMore;
229            }
230
231            return OMX_ErrorNone;
232        }
233
234        default:
235            return SimpleSoftOMXComponent::internalSetParameter(index, params);
236    }
237}
238
239OMX_ERRORTYPE SoftVideoDecoderOMXComponent::getConfig(
240        OMX_INDEXTYPE index, OMX_PTR params) {
241    switch (index) {
242        case OMX_IndexConfigCommonOutputCrop:
243        {
244            OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)params;
245
246            if (rectParams->nPortIndex != kOutputPortIndex) {
247                return OMX_ErrorUndefined;
248            }
249
250            rectParams->nLeft = mCropLeft;
251            rectParams->nTop = mCropTop;
252            rectParams->nWidth = mCropWidth;
253            rectParams->nHeight = mCropHeight;
254
255            return OMX_ErrorNone;
256        }
257
258        default:
259            return OMX_ErrorUnsupportedIndex;
260    }
261}
262
263void SoftVideoDecoderOMXComponent::onReset() {
264    mOutputPortSettingsChange = NONE;
265}
266
267void SoftVideoDecoderOMXComponent::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
268    if (portIndex != kOutputPortIndex) {
269        return;
270    }
271
272    switch (mOutputPortSettingsChange) {
273        case NONE:
274            break;
275
276        case AWAITING_DISABLED:
277        {
278            CHECK(!enabled);
279            mOutputPortSettingsChange = AWAITING_ENABLED;
280            break;
281        }
282
283        default:
284        {
285            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
286            CHECK(enabled);
287            mOutputPortSettingsChange = NONE;
288            break;
289        }
290    }
291}
292
293}  // namespace android
294