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 "SoftVPX"
19bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <utils/Log.h>
20bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
21bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include "SoftVPX.h"
22bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
23bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <media/stagefright/foundation/ADebug.h>
24bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <media/stagefright/MediaDefs.h>
25bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
26bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include "vpx/vpx_decoder.h"
27bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include "vpx/vpx_codec.h"
28bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include "vpx/vp8dx.h"
29bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
30bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubernamespace android {
31bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
32bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubertemplate<class T>
33bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberstatic void InitOMXParams(T *params) {
34bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nSize = sizeof(T);
35bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nVersion.s.nVersionMajor = 1;
36bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nVersion.s.nVersionMinor = 0;
37bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nVersion.s.nRevision = 0;
38bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nVersion.s.nStep = 0;
39bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
40bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
41bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberSoftVPX::SoftVPX(
42bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const char *name,
43bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const OMX_CALLBACKTYPE *callbacks,
44bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_PTR appData,
45bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_COMPONENTTYPE **component)
46bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    : SimpleSoftOMXComponent(name, callbacks, appData, component),
47bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mCtx(NULL),
48bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mWidth(320),
49bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mHeight(240),
50bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mOutputPortSettingsChange(NONE) {
51bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    initPorts();
52bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    CHECK_EQ(initDecoder(), (status_t)OK);
53bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
54bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
55bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberSoftVPX::~SoftVPX() {
56bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    vpx_codec_destroy((vpx_codec_ctx_t *)mCtx);
57bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    delete (vpx_codec_ctx_t *)mCtx;
58bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    mCtx = NULL;
59bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
60bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
61bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftVPX::initPorts() {
62bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    OMX_PARAM_PORTDEFINITIONTYPE def;
63bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    InitOMXParams(&def);
64bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
65bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nPortIndex = 0;
66bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.eDir = OMX_DirInput;
67bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferCountMin = kNumBuffers;
68bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferCountActual = def.nBufferCountMin;
6967f43688334bcd72ae7c3b5b386c1b6a34711f4fAndreas Huber    def.nBufferSize = 256 * 1024;
70bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bEnabled = OMX_TRUE;
71bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bPopulated = OMX_FALSE;
72bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.eDomain = OMX_PortDomainVideo;
73bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bBuffersContiguous = OMX_FALSE;
74bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferAlignment = 1;
75bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
76bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VPX);
77bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.pNativeRender = NULL;
78bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.nFrameWidth = mWidth;
79bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.nFrameHeight = mHeight;
80bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.nStride = def.format.video.nFrameWidth;
81bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.nSliceHeight = def.format.video.nFrameHeight;
82bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.nBitrate = 0;
83bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.xFramerate = 0;
84bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.bFlagErrorConcealment = OMX_FALSE;
85bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.eCompressionFormat = OMX_VIDEO_CodingVPX;
86bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
87bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.pNativeWindow = NULL;
88bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
89bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    addPort(def);
90bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
91bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nPortIndex = 1;
92bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.eDir = OMX_DirOutput;
93bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferCountMin = kNumBuffers;
94bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferCountActual = def.nBufferCountMin;
95bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bEnabled = OMX_TRUE;
96bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bPopulated = OMX_FALSE;
97bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.eDomain = OMX_PortDomainVideo;
98bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bBuffersContiguous = OMX_FALSE;
99bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferAlignment = 2;
100bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
101bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
102bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.pNativeRender = NULL;
103bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.nFrameWidth = mWidth;
104bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.nFrameHeight = mHeight;
105bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.nStride = def.format.video.nFrameWidth;
106bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.nSliceHeight = def.format.video.nFrameHeight;
107bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.nBitrate = 0;
108bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.xFramerate = 0;
109bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.bFlagErrorConcealment = OMX_FALSE;
110bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
111bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
112bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.video.pNativeWindow = NULL;
113bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
114bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferSize =
115bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2;
116bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
117bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    addPort(def);
118bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
119bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
120f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dongstatic int GetCPUCoreCount() {
121f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong    int cpuCoreCount = 1;
122f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong#if defined(_SC_NPROCESSORS_ONLN)
123f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong    cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
124f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong#else
125f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong    // _SC_NPROC_ONLN must be defined...
126f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong    cpuCoreCount = sysconf(_SC_NPROC_ONLN);
127f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong#endif
128f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong    CHECK(cpuCoreCount >= 1);
1293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("Number of CPU cores: %d", cpuCoreCount);
130f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong    return cpuCoreCount;
131f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong}
132f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong
133bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberstatus_t SoftVPX::initDecoder() {
134bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    mCtx = new vpx_codec_ctx_t;
135bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    vpx_codec_err_t vpx_err;
136f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong    vpx_codec_dec_cfg_t cfg;
137f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong    memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t));
138f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong    cfg.threads = GetCPUCoreCount();
139bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if ((vpx_err = vpx_codec_dec_init(
140f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong                (vpx_codec_ctx_t *)mCtx, &vpx_codec_vp8_dx_algo, &cfg, 0))) {
14129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("on2 decoder failed to initialize. (%d)", vpx_err);
142bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        return UNKNOWN_ERROR;
143bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
144bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
145bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    return OK;
146bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
147bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
148bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberOMX_ERRORTYPE SoftVPX::internalGetParameter(
149bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_INDEXTYPE index, OMX_PTR params) {
150bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    switch (index) {
151bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case OMX_IndexParamVideoPortFormat:
152bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
153bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
154bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
155bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
156bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (formatParams->nPortIndex > 1) {
157bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return OMX_ErrorUndefined;
158bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
159bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
160bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (formatParams->nIndex != 0) {
161bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return OMX_ErrorNoMore;
162bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
163bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
164bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (formatParams->nPortIndex == 0) {
165bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                formatParams->eCompressionFormat = OMX_VIDEO_CodingVPX;
166bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
167bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                formatParams->xFramerate = 0;
168bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            } else {
169bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                CHECK_EQ(formatParams->nPortIndex, 1u);
170bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
171bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
172bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
173bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                formatParams->xFramerate = 0;
174bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
175bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
176bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return OMX_ErrorNone;
177bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
178bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
179bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        default:
180bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return SimpleSoftOMXComponent::internalGetParameter(index, params);
181bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
182bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
183bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
184bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberOMX_ERRORTYPE SoftVPX::internalSetParameter(
185bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_INDEXTYPE index, const OMX_PTR params) {
186bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    switch (index) {
187bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case OMX_IndexParamStandardComponentRole:
188bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
189bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
190bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                (const OMX_PARAM_COMPONENTROLETYPE *)params;
191bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
192bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (strncmp((const char *)roleParams->cRole,
193bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                        "video_decoder.vpx",
194bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                        OMX_MAX_STRINGNAME_SIZE - 1)) {
195bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return OMX_ErrorUndefined;
196bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
197bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
198bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return OMX_ErrorNone;
199bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
200bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
201bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case OMX_IndexParamVideoPortFormat:
202bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
203bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
204bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
205bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
206bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (formatParams->nPortIndex > 1) {
207bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return OMX_ErrorUndefined;
208bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
209bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
210bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (formatParams->nIndex != 0) {
211bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return OMX_ErrorNoMore;
212bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
213bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
214bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return OMX_ErrorNone;
215bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
216bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
217bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        default:
218bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return SimpleSoftOMXComponent::internalSetParameter(index, params);
219bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
220bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
221bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
222bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftVPX::onQueueFilled(OMX_U32 portIndex) {
223bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (mOutputPortSettingsChange != NONE) {
224bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        return;
225bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
226bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
227bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    List<BufferInfo *> &inQueue = getPortQueue(0);
228bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    List<BufferInfo *> &outQueue = getPortQueue(1);
229bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
230bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    while (!inQueue.empty() && !outQueue.empty()) {
231bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        BufferInfo *inInfo = *inQueue.begin();
232bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
233bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
234bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        BufferInfo *outInfo = *outQueue.begin();
235bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
236bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
237bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
238bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            inQueue.erase(inQueue.begin());
239bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            inInfo->mOwnedByUs = false;
240bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            notifyEmptyBufferDone(inHeader);
241bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
242bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outHeader->nFilledLen = 0;
243bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
244bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
245bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outQueue.erase(outQueue.begin());
246bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outInfo->mOwnedByUs = false;
247bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            notifyFillBufferDone(outHeader);
248bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return;
249bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
250bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
251bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if (vpx_codec_decode(
252bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                    (vpx_codec_ctx_t *)mCtx,
253bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                    inHeader->pBuffer + inHeader->nOffset,
254bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                    inHeader->nFilledLen,
255bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                    NULL,
256bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                    0)) {
25729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("on2 decoder failed to decode frame.");
258bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
259bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
260bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return;
261bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
262bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
263bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        vpx_codec_iter_t iter = NULL;
264bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        vpx_image_t *img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);
265bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
266bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if (img != NULL) {
267bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK_EQ(img->fmt, IMG_FMT_I420);
268bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
269bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            int32_t width = img->d_w;
270bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            int32_t height = img->d_h;
271bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
272bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (width != mWidth || height != mHeight) {
273bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                mWidth = width;
274bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                mHeight = height;
275bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
276bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                updatePortDefinitions();
277bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
278bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
279bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                mOutputPortSettingsChange = AWAITING_DISABLED;
280bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return;
281bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
282bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
283bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outHeader->nOffset = 0;
284bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outHeader->nFilledLen = (width * height * 3) / 2;
285bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outHeader->nFlags = 0;
286bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outHeader->nTimeStamp = inHeader->nTimeStamp;
287bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
288bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y];
289bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            uint8_t *dst = outHeader->pBuffer;
290bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            for (size_t i = 0; i < img->d_h; ++i) {
291bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                memcpy(dst, srcLine, img->d_w);
292bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
293bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                srcLine += img->stride[PLANE_Y];
294bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                dst += img->d_w;
295bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
296bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
297bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            srcLine = (const uint8_t *)img->planes[PLANE_U];
298bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            for (size_t i = 0; i < img->d_h / 2; ++i) {
299bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                memcpy(dst, srcLine, img->d_w / 2);
300bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
301bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                srcLine += img->stride[PLANE_U];
302bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                dst += img->d_w / 2;
303bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
304bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
305bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            srcLine = (const uint8_t *)img->planes[PLANE_V];
306bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            for (size_t i = 0; i < img->d_h / 2; ++i) {
307bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                memcpy(dst, srcLine, img->d_w / 2);
308bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
309bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                srcLine += img->stride[PLANE_V];
310bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                dst += img->d_w / 2;
311bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
312bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
313bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outInfo->mOwnedByUs = false;
314bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outQueue.erase(outQueue.begin());
315bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outInfo = NULL;
316bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            notifyFillBufferDone(outHeader);
317bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outHeader = NULL;
318bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
319bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
320bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        inInfo->mOwnedByUs = false;
321bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        inQueue.erase(inQueue.begin());
322bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        inInfo = NULL;
323bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        notifyEmptyBufferDone(inHeader);
324bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        inHeader = NULL;
325bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
326bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
327bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
328bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftVPX::onPortFlushCompleted(OMX_U32 portIndex) {
329bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
330bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
331bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftVPX::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
332bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (portIndex != 1) {
333bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        return;
334bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
335bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
336bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    switch (mOutputPortSettingsChange) {
337bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case NONE:
338bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            break;
339bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
340bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case AWAITING_DISABLED:
341bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
342bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK(!enabled);
343bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mOutputPortSettingsChange = AWAITING_ENABLED;
344bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            break;
345bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
346bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
347bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        default:
348bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
349bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
350bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK(enabled);
351bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mOutputPortSettingsChange = NONE;
352bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            break;
353bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
354bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
355bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
356bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
357bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftVPX::updatePortDefinitions() {
358bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef;
359bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def->format.video.nFrameWidth = mWidth;
360bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def->format.video.nFrameHeight = mHeight;
361bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def->format.video.nStride = def->format.video.nFrameWidth;
362bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def->format.video.nSliceHeight = def->format.video.nFrameHeight;
363bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
364bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def = &editPortInfo(1)->mDef;
365bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def->format.video.nFrameWidth = mWidth;
366bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def->format.video.nFrameHeight = mHeight;
367bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def->format.video.nStride = def->format.video.nFrameWidth;
368bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def->format.video.nSliceHeight = def->format.video.nFrameHeight;
369bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
370bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def->nBufferSize =
371bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        (def->format.video.nFrameWidth
372bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            * def->format.video.nFrameHeight * 3) / 2;
373bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
374bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
375bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}  // namespace android
376bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
377bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberandroid::SoftOMXComponent *createSoftOMXComponent(
378bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const char *name, const OMX_CALLBACKTYPE *callbacks,
379bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
380bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    return new android::SoftVPX(name, callbacks, appData, component);
381bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
382bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
383