1bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber/*
2bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Copyright (C) 2011 The Android Open Source Project
3bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber *
4bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * you may not use this file except in compliance with the License.
6bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * You may obtain a copy of the License at
7bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber *
8bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber *
10bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Unless required by applicable law or agreed to in writing, software
11bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * See the License for the specific language governing permissions and
14bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * limitations under the License.
15bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber */
16bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
17bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber//#define LOG_NDEBUG 0
18bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#define LOG_TAG "SoftMPEG4"
19bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <utils/Log.h>
20bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
21bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include "SoftMPEG4.h"
22bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
23bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <media/stagefright/foundation/ADebug.h>
24a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar#include <media/stagefright/foundation/AUtils.h>
25bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <media/stagefright/MediaDefs.h>
26bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <media/stagefright/MediaErrors.h>
27457116d3a01618acf9a875020ca5860551ba03a6James Dong#include <media/IOMX.h>
28bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
29bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include "mp4dec_api.h"
30bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
31bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubernamespace android {
32bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
33457116d3a01618acf9a875020ca5860551ba03a6James Dongstatic const CodecProfileLevel kM4VProfileLevels[] = {
34457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0 },
35457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level0b },
36457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level1 },
37457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level2 },
38457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level3 },
39457116d3a01618acf9a875020ca5860551ba03a6James Dong};
40457116d3a01618acf9a875020ca5860551ba03a6James Dong
41457116d3a01618acf9a875020ca5860551ba03a6James Dongstatic const CodecProfileLevel kH263ProfileLevels[] = {
42457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level10 },
43457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level20 },
44457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level30 },
45457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level45 },
46457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level10 },
47457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level20 },
48457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level30 },
49457116d3a01618acf9a875020ca5860551ba03a6James Dong    { OMX_VIDEO_H263ProfileISWV2,    OMX_VIDEO_H263Level45 },
50457116d3a01618acf9a875020ca5860551ba03a6James Dong};
51457116d3a01618acf9a875020ca5860551ba03a6James Dong
52bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberSoftMPEG4::SoftMPEG4(
53bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const char *name,
547f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar        const char *componentRole,
557f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar        OMX_VIDEO_CODINGTYPE codingType,
567f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar        const CodecProfileLevel *profileLevels,
577f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar        size_t numProfileLevels,
58bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const OMX_CALLBACKTYPE *callbacks,
59bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_PTR appData,
60bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_COMPONENTTYPE **component)
617f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    : SoftVideoDecoderOMXComponent(
627f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar            name, componentRole, codingType, profileLevels, numProfileLevels,
637f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar            352 /* width */, 288 /* height */, callbacks, appData, component),
647f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar      mMode(codingType == OMX_VIDEO_CodingH263 ? MODE_H263 : MODE_MPEG4),
65bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mHandle(new tagvideoDecControls),
66bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mInputBufferCount(0),
67bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mSignalledError(false),
68bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mInitialized(false),
69bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mFramesConfigured(false),
70bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mNumSamplesOutput(0),
717f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar      mPvTime(0) {
727f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    initPorts(
737f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar            kNumInputBuffers,
74a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar            352 * 288 * 3 / 2 /* minInputBufferSize */,
757f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar            kNumOutputBuffers,
767f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar            (mMode == MODE_MPEG4)
777f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar            ? MEDIA_MIMETYPE_VIDEO_MPEG4 : MEDIA_MIMETYPE_VIDEO_H263);
78bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    CHECK_EQ(initDecoder(), (status_t)OK);
79bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
80bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
81bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberSoftMPEG4::~SoftMPEG4() {
82bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (mInitialized) {
83bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        PVCleanUpVideoDecoder(mHandle);
84bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
85bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
86bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    delete mHandle;
87bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    mHandle = NULL;
88bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
89bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
90bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberstatus_t SoftMPEG4::initDecoder() {
91bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    memset(mHandle, 0, sizeof(tagvideoDecControls));
92bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    return OK;
93bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
94bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
9584333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftMPEG4::onQueueFilled(OMX_U32 /* portIndex */) {
96bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (mSignalledError || mOutputPortSettingsChange != NONE) {
97bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        return;
98bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
99bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
100bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    List<BufferInfo *> &inQueue = getPortQueue(0);
101bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    List<BufferInfo *> &outQueue = getPortQueue(1);
102bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
103bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    while (!inQueue.empty() && outQueue.size() == kNumOutputBuffers) {
104bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        BufferInfo *inInfo = *inQueue.begin();
105bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
106fd866b3aa0d97375de08f8888b95669026c83361Wei Jia        if (inHeader == NULL) {
107fd866b3aa0d97375de08f8888b95669026c83361Wei Jia            inQueue.erase(inQueue.begin());
108fd866b3aa0d97375de08f8888b95669026c83361Wei Jia            inInfo->mOwnedByUs = false;
109fd866b3aa0d97375de08f8888b95669026c83361Wei Jia            continue;
110fd866b3aa0d97375de08f8888b95669026c83361Wei Jia        }
111bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
112bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        PortInfo *port = editPortInfo(1);
113bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
114bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_BUFFERHEADERTYPE *outHeader =
115bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            port->mBuffers.editItemAt(mNumSamplesOutput & 1).mHeader;
116bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
117fd866b3aa0d97375de08f8888b95669026c83361Wei Jia        if (inHeader->nFilledLen == 0) {
118bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            inQueue.erase(inQueue.begin());
119bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            inInfo->mOwnedByUs = false;
120bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            notifyEmptyBufferDone(inHeader);
121bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
122bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            ++mInputBufferCount;
123bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
124fd866b3aa0d97375de08f8888b95669026c83361Wei Jia            if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
125fd866b3aa0d97375de08f8888b95669026c83361Wei Jia                outHeader->nFilledLen = 0;
126fd866b3aa0d97375de08f8888b95669026c83361Wei Jia                outHeader->nFlags = OMX_BUFFERFLAG_EOS;
127bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
128fd866b3aa0d97375de08f8888b95669026c83361Wei Jia                List<BufferInfo *>::iterator it = outQueue.begin();
129fd866b3aa0d97375de08f8888b95669026c83361Wei Jia                while ((*it)->mHeader != outHeader) {
130fd866b3aa0d97375de08f8888b95669026c83361Wei Jia                    ++it;
131fd866b3aa0d97375de08f8888b95669026c83361Wei Jia                }
132bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
133fd866b3aa0d97375de08f8888b95669026c83361Wei Jia                BufferInfo *outInfo = *it;
134fd866b3aa0d97375de08f8888b95669026c83361Wei Jia                outInfo->mOwnedByUs = false;
135fd866b3aa0d97375de08f8888b95669026c83361Wei Jia                outQueue.erase(it);
136fd866b3aa0d97375de08f8888b95669026c83361Wei Jia                outInfo = NULL;
137bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
138fd866b3aa0d97375de08f8888b95669026c83361Wei Jia                notifyFillBufferDone(outHeader);
139fd866b3aa0d97375de08f8888b95669026c83361Wei Jia                outHeader = NULL;
140fd866b3aa0d97375de08f8888b95669026c83361Wei Jia            }
141bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return;
142bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
143bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
144bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        uint8_t *bitstream = inHeader->pBuffer + inHeader->nOffset;
145a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu        uint32_t *start_code = (uint32_t *)bitstream;
146a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu        bool volHeader = *start_code == 0xB0010000;
147a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu        if (volHeader) {
148a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu            PVCleanUpVideoDecoder(mHandle);
149a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu            mInitialized = false;
150a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu        }
151bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
152bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if (!mInitialized) {
153bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            uint8_t *vol_data[1];
154bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            int32_t vol_size = 0;
155bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
156bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            vol_data[0] = NULL;
157bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
158a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu            if ((inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) || volHeader) {
159bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                vol_data[0] = bitstream;
160bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                vol_size = inHeader->nFilledLen;
161bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
162bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
163bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            MP4DecodingMode mode =
164bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                (mMode == MODE_MPEG4) ? MPEG4_MODE : H263_MODE;
165bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
166bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            Bool success = PVInitVideoDecoder(
1670f694a12f92a01f95807242320bd65e88c699708Ronghua Wu                    mHandle, vol_data, &vol_size, 1,
1680f694a12f92a01f95807242320bd65e88c699708Ronghua Wu                    outputBufferWidth(), outputBufferHeight(), mode);
169bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
170bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (!success) {
1715ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                ALOGW("PVInitVideoDecoder failed. Unsupported content?");
172bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
173bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
174bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                mSignalledError = true;
175bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return;
176bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
177bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
178bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            MP4DecodingMode actualMode = PVGetDecBitstreamMode(mHandle);
179bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (mode != actualMode) {
180bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
181bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                mSignalledError = true;
182bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return;
183bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
184bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
185bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            PVSetPostProcType((VideoDecControls *) mHandle, 0);
186bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
187a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu            bool hasFrameData = false;
188bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
189bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                inInfo->mOwnedByUs = false;
190bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                inQueue.erase(inQueue.begin());
191bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                inInfo = NULL;
192bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                notifyEmptyBufferDone(inHeader);
193bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                inHeader = NULL;
194a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu            } else if (volHeader) {
195a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu                hasFrameData = true;
196bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
197bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
198bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mInitialized = true;
199bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
200a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu            if (mode == MPEG4_MODE && handlePortSettingsChange()) {
201bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return;
202bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
203bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
204a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu            if (!hasFrameData) {
205a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu                continue;
206a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu            }
207bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
208bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
209bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if (!mFramesConfigured) {
210bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            PortInfo *port = editPortInfo(1);
211bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            OMX_BUFFERHEADERTYPE *outHeader = port->mBuffers.editItemAt(1).mHeader;
212bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
213695123195034402ca76169b195069c28c30342d3Pawin Vongmasa            OMX_U32 yFrameSize = sizeof(uint8) * mHandle->size;
214695123195034402ca76169b195069c28c30342d3Pawin Vongmasa            if ((outHeader->nAllocLen < yFrameSize) ||
215695123195034402ca76169b195069c28c30342d3Pawin Vongmasa                    (outHeader->nAllocLen - yFrameSize < yFrameSize / 2)) {
216baa9146401e28c5acf54dea21ddd197f0d3a8fcdPawin Vongmasa                ALOGE("Too small output buffer for reference frame: %lu bytes",
217baa9146401e28c5acf54dea21ddd197f0d3a8fcdPawin Vongmasa                        (unsigned long)outHeader->nAllocLen);
218695123195034402ca76169b195069c28c30342d3Pawin Vongmasa                android_errorWriteLog(0x534e4554, "30033990");
219695123195034402ca76169b195069c28c30342d3Pawin Vongmasa                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
220695123195034402ca76169b195069c28c30342d3Pawin Vongmasa                mSignalledError = true;
221695123195034402ca76169b195069c28c30342d3Pawin Vongmasa                return;
222695123195034402ca76169b195069c28c30342d3Pawin Vongmasa            }
223bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            PVSetReferenceYUV(mHandle, outHeader->pBuffer);
224bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mFramesConfigured = true;
225bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
226bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
227f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber        uint32_t useExtTimestamp = (inHeader->nOffset == 0);
228f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber
229269a355679fce6a71523faeefc2ff575abbd1a8eLajos Molnar        // decoder deals in ms (int32_t), OMX in us (int64_t)
230269a355679fce6a71523faeefc2ff575abbd1a8eLajos Molnar        // so use fake timestamp instead
231269a355679fce6a71523faeefc2ff575abbd1a8eLajos Molnar        uint32_t timestamp = 0xFFFFFFFF;
232269a355679fce6a71523faeefc2ff575abbd1a8eLajos Molnar        if (useExtTimestamp) {
233269a355679fce6a71523faeefc2ff575abbd1a8eLajos Molnar            mPvToOmxTimeMap.add(mPvTime, inHeader->nTimeStamp);
234269a355679fce6a71523faeefc2ff575abbd1a8eLajos Molnar            timestamp = mPvTime;
235269a355679fce6a71523faeefc2ff575abbd1a8eLajos Molnar            mPvTime++;
236269a355679fce6a71523faeefc2ff575abbd1a8eLajos Molnar        }
237f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber
238bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        int32_t bufferSize = inHeader->nFilledLen;
23902accddf8d69da7b2b5e05631ad222cd842ff547Andreas Huber        int32_t tmp = bufferSize;
240bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
241695123195034402ca76169b195069c28c30342d3Pawin Vongmasa        OMX_U32 frameSize;
242695123195034402ca76169b195069c28c30342d3Pawin Vongmasa        OMX_U64 yFrameSize = (OMX_U64)mWidth * (OMX_U64)mHeight;
243695123195034402ca76169b195069c28c30342d3Pawin Vongmasa        if (yFrameSize > ((OMX_U64)UINT32_MAX / 3) * 2) {
244695123195034402ca76169b195069c28c30342d3Pawin Vongmasa            ALOGE("Frame size too large");
245695123195034402ca76169b195069c28c30342d3Pawin Vongmasa            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
246695123195034402ca76169b195069c28c30342d3Pawin Vongmasa            mSignalledError = true;
247695123195034402ca76169b195069c28c30342d3Pawin Vongmasa            return;
248695123195034402ca76169b195069c28c30342d3Pawin Vongmasa        }
249695123195034402ca76169b195069c28c30342d3Pawin Vongmasa        frameSize = (OMX_U32)(yFrameSize + (yFrameSize / 2));
250695123195034402ca76169b195069c28c30342d3Pawin Vongmasa
2513a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim        if (outHeader->nAllocLen < frameSize) {
2523a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim            android_errorWriteLog(0x534e4554, "27833616");
2533a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim            ALOGE("Insufficient output buffer size");
2543a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
2553a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim            mSignalledError = true;
2563a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim            return;
2573a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim        }
25826557d832fde349721500b47d51467c046794ae9Wei Jia
25926557d832fde349721500b47d51467c046794ae9Wei Jia        // Need to check if header contains new info, e.g., width/height, etc.
26026557d832fde349721500b47d51467c046794ae9Wei Jia        VopHeaderInfo header_info;
26126557d832fde349721500b47d51467c046794ae9Wei Jia        uint8_t *bitstreamTmp = bitstream;
26226557d832fde349721500b47d51467c046794ae9Wei Jia        if (PVDecodeVopHeader(
26326557d832fde349721500b47d51467c046794ae9Wei Jia                    mHandle, &bitstreamTmp, &timestamp, &tmp,
26426557d832fde349721500b47d51467c046794ae9Wei Jia                    &header_info, &useExtTimestamp,
26526557d832fde349721500b47d51467c046794ae9Wei Jia                    outHeader->pBuffer) != PV_TRUE) {
26626557d832fde349721500b47d51467c046794ae9Wei Jia            ALOGE("failed to decode vop header.");
26726557d832fde349721500b47d51467c046794ae9Wei Jia
26826557d832fde349721500b47d51467c046794ae9Wei Jia            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
26926557d832fde349721500b47d51467c046794ae9Wei Jia            mSignalledError = true;
27026557d832fde349721500b47d51467c046794ae9Wei Jia            return;
27126557d832fde349721500b47d51467c046794ae9Wei Jia        }
27226557d832fde349721500b47d51467c046794ae9Wei Jia        if (handlePortSettingsChange()) {
27326557d832fde349721500b47d51467c046794ae9Wei Jia            return;
27426557d832fde349721500b47d51467c046794ae9Wei Jia        }
27526557d832fde349721500b47d51467c046794ae9Wei Jia
2760029faf8f4efbca3844c4174b75d46c432f8f272Andreas Huber        // The PV decoder is lying to us, sometimes it'll claim to only have
2770029faf8f4efbca3844c4174b75d46c432f8f272Andreas Huber        // consumed a subset of the buffer when it clearly consumed all of it.
2780029faf8f4efbca3844c4174b75d46c432f8f272Andreas Huber        // ignore whatever it says...
27926557d832fde349721500b47d51467c046794ae9Wei Jia        if (PVDecodeVopBody(mHandle, &tmp) != PV_TRUE) {
28029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("failed to decode video frame.");
281bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
282bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
283bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mSignalledError = true;
284bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return;
285bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
286bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
287a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu        // H263 doesn't have VOL header, the frame size information is in short header, i.e. the
288a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu        // decoder may detect size change after PVDecodeVideoFrame.
289a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu        if (handlePortSettingsChange()) {
290bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return;
291bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
292bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
293f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber        // decoder deals in ms, OMX in us.
294269a355679fce6a71523faeefc2ff575abbd1a8eLajos Molnar        outHeader->nTimeStamp = mPvToOmxTimeMap.valueFor(timestamp);
295269a355679fce6a71523faeefc2ff575abbd1a8eLajos Molnar        mPvToOmxTimeMap.removeItem(timestamp);
296bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
29702accddf8d69da7b2b5e05631ad222cd842ff547Andreas Huber        inHeader->nOffset += bufferSize;
29802accddf8d69da7b2b5e05631ad222cd842ff547Andreas Huber        inHeader->nFilledLen = 0;
2994c44e9fed87ff6363393f2559b150291242da247Marco Nelissen        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
3004c44e9fed87ff6363393f2559b150291242da247Marco Nelissen            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
3014c44e9fed87ff6363393f2559b150291242da247Marco Nelissen        } else {
3024c44e9fed87ff6363393f2559b150291242da247Marco Nelissen            outHeader->nFlags = 0;
3034c44e9fed87ff6363393f2559b150291242da247Marco Nelissen        }
304f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber
305f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber        if (inHeader->nFilledLen == 0) {
306f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber            inInfo->mOwnedByUs = false;
307f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber            inQueue.erase(inQueue.begin());
308f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber            inInfo = NULL;
309f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber            notifyEmptyBufferDone(inHeader);
310f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber            inHeader = NULL;
311f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber        }
312bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
313bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ++mInputBufferCount;
314bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
315bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outHeader->nOffset = 0;
3163a3c3f7fc658ef874f82e46857ad9df3616aac95Wonsik Kim        outHeader->nFilledLen = frameSize;
317bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
318bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        List<BufferInfo *>::iterator it = outQueue.begin();
319bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        while ((*it)->mHeader != outHeader) {
320bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            ++it;
321bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
322bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
323bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        BufferInfo *outInfo = *it;
324bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outInfo->mOwnedByUs = false;
325bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outQueue.erase(it);
326bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outInfo = NULL;
327bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
328bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        notifyFillBufferDone(outHeader);
329bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outHeader = NULL;
330bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
331bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ++mNumSamplesOutput;
332bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
333bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
334bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
335a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wubool SoftMPEG4::handlePortSettingsChange() {
3367f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    uint32_t disp_width, disp_height;
3377f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    PVGetVideoDimensions(mHandle, (int32 *)&disp_width, (int32 *)&disp_height);
338bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
3397f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    uint32_t buf_width, buf_height;
3407f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    PVGetBufferDimensions(mHandle, (int32 *)&buf_width, (int32 *)&buf_height);
341bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
342bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    CHECK_LE(disp_width, buf_width);
343bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    CHECK_LE(disp_height, buf_height);
344bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
3453856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("disp_width = %d, disp_height = %d, buf_width = %d, buf_height = %d",
346bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            disp_width, disp_height, buf_width, buf_height);
347bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
348d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu    CropSettingsMode cropSettingsMode = kCropUnSet;
349d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu    if (disp_width != buf_width || disp_height != buf_height) {
350d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu        cropSettingsMode = kCropSet;
351d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu
352d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu        if (mCropWidth != disp_width || mCropHeight != disp_height) {
353d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu            mCropLeft = 0;
354d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu            mCropTop = 0;
355d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu            mCropWidth = disp_width;
356d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu            mCropHeight = disp_height;
357d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu            cropSettingsMode = kCropChanged;
358d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu        }
359bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
360bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
361a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu    bool portWillReset = false;
362a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu    const bool fakeStride = true;
363a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu    SoftVideoDecoderOMXComponent::handlePortSettingsChange(
364d5a2f55034022f2d0425fa0701894d0c4787b726Ronghua Wu            &portWillReset, buf_width, buf_height, cropSettingsMode, fakeStride);
365a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu    if (portWillReset) {
366bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if (mMode == MODE_H263) {
367bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            PVCleanUpVideoDecoder(mHandle);
368bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
369bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            uint8_t *vol_data[1];
370bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            int32_t vol_size = 0;
371bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
372bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            vol_data[0] = NULL;
373bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (!PVInitVideoDecoder(
3740f694a12f92a01f95807242320bd65e88c699708Ronghua Wu                    mHandle, vol_data, &vol_size, 1, outputBufferWidth(), outputBufferHeight(),
375bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                    H263_MODE)) {
376bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
377bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                mSignalledError = true;
378bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return true;
379bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
380bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
381bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
382bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mFramesConfigured = false;
383bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
384bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
385a694dd0ce2caaf921f7bc894df87a5d52594b4ebRonghua Wu    return portWillReset;
386bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
387bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
388bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftMPEG4::onPortFlushCompleted(OMX_U32 portIndex) {
389bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (portIndex == 0 && mInitialized) {
390bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        CHECK_EQ((int)PVResetVideoDecoder(mHandle), (int)PV_TRUE);
391bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
392bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
393bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
394d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Hubervoid SoftMPEG4::onReset() {
3957f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    SoftVideoDecoderOMXComponent::onReset();
396269a355679fce6a71523faeefc2ff575abbd1a8eLajos Molnar    mPvToOmxTimeMap.clear();
397d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Huber    mSignalledError = false;
39853b0a2b1f9cb6b99b3f0d1a639921d1b24bc30b7Lajos Molnar    mFramesConfigured = false;
39953b0a2b1f9cb6b99b3f0d1a639921d1b24bc30b7Lajos Molnar    if (mInitialized) {
40053b0a2b1f9cb6b99b3f0d1a639921d1b24bc30b7Lajos Molnar        PVCleanUpVideoDecoder(mHandle);
40153b0a2b1f9cb6b99b3f0d1a639921d1b24bc30b7Lajos Molnar        mInitialized = false;
40253b0a2b1f9cb6b99b3f0d1a639921d1b24bc30b7Lajos Molnar    }
403d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Huber}
404d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Huber
405a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnarvoid SoftMPEG4::updatePortDefinitions(bool updateCrop, bool updateInputSize) {
406a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar    SoftVideoDecoderOMXComponent::updatePortDefinitions(updateCrop, updateInputSize);
407bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
4087f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    /* We have to align our width and height - this should affect stride! */
4097f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef;
410a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar    def->format.video.nStride = align(def->format.video.nStride, 16);
411a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar    def->format.video.nSliceHeight = align(def->format.video.nSliceHeight, 16);
412a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar    def->nBufferSize = (def->format.video.nStride * def->format.video.nSliceHeight * 3) / 2;
413bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
414bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
415bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}  // namespace android
416bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
417bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberandroid::SoftOMXComponent *createSoftOMXComponent(
418bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const char *name, const OMX_CALLBACKTYPE *callbacks,
419bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
4207f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    using namespace android;
4217f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    if (!strcmp(name, "OMX.google.h263.decoder")) {
4227f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar        return new android::SoftMPEG4(
4237f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar                name, "video_decoder.h263", OMX_VIDEO_CodingH263,
4247f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar                kH263ProfileLevels, ARRAY_SIZE(kH263ProfileLevels),
4257f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar                callbacks, appData, component);
4267f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    } else if (!strcmp(name, "OMX.google.mpeg4.decoder")) {
4277f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar        return new android::SoftMPEG4(
4287f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar                name, "video_decoder.mpeg4", OMX_VIDEO_CodingMPEG4,
4297f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar                kM4VProfileLevels, ARRAY_SIZE(kM4VProfileLevels),
4307f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar                callbacks, appData, component);
4317f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    } else {
4327f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar        CHECK(!"Unknown component");
4337f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar    }
434dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn    return NULL;
435bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
436bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
437