SoftVideoEncoderOMXComponent.cpp revision 8c953e45f3431f8e1c04f8973fe8bdebf7e61033
11ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni/*
21ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni * Copyright 2014 The Android Open Source Project
3da0f069871343119251d6b0586be356dc2146a62Yang Ni *
4433558f0f9abbf07770db288183a15fd261cace2Yabin Cui * Licensed under the Apache License, Version 2.0 (the "License");
5433558f0f9abbf07770db288183a15fd261cace2Yabin Cui * you may not use this file except in compliance with the License.
6433558f0f9abbf07770db288183a15fd261cace2Yabin Cui * You may obtain a copy of the License at
7da0f069871343119251d6b0586be356dc2146a62Yang Ni *
8062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni *      http://www.apache.org/licenses/LICENSE-2.0
9062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni *
10da0f069871343119251d6b0586be356dc2146a62Yang Ni * Unless required by applicable law or agreed to in writing, software
11da0f069871343119251d6b0586be356dc2146a62Yang Ni * distributed under the License is distributed on an "AS IS" BASIS,
12da0f069871343119251d6b0586be356dc2146a62Yang Ni * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13da0f069871343119251d6b0586be356dc2146a62Yang Ni * See the License for the specific language governing permissions and
14da0f069871343119251d6b0586be356dc2146a62Yang Ni * limitations under the License.
15da0f069871343119251d6b0586be356dc2146a62Yang Ni */
16da0f069871343119251d6b0586be356dc2146a62Yang Ni
17da0f069871343119251d6b0586be356dc2146a62Yang Ni#include <inttypes.h>
181ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
191ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni//#define LOG_NDEBUG 0
201ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#define LOG_TAG "SoftVideoEncoderOMXComponent"
211ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <utils/Log.h>
222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include <utils/misc.h>
231ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
241ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include "include/SoftVideoEncoderOMXComponent.h"
251ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
26da0f069871343119251d6b0586be356dc2146a62Yang Ni#include <media/hardware/HardwareAPI.h>
27da0f069871343119251d6b0586be356dc2146a62Yang Ni#include <media/stagefright/foundation/ADebug.h>
28da0f069871343119251d6b0586be356dc2146a62Yang Ni#include <media/stagefright/foundation/ALooper.h>
29da0f069871343119251d6b0586be356dc2146a62Yang Ni#include <media/stagefright/foundation/AMessage.h>
301ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <media/stagefright/foundation/AUtils.h>
311ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <media/stagefright/MediaDefs.h>
321ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
331ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <ui/GraphicBuffer.h>
341ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <ui/GraphicBufferMapper.h>
351ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
36da0f069871343119251d6b0586be356dc2146a62Yang Ni#include <OMX_IndexExt.h>
371ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
381ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ninamespace android {
391ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
40ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Niconst static OMX_COLOR_FORMATTYPE kSupportedColorFormats[] = {
41eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    OMX_COLOR_FormatYUV420Planar,
42eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    OMX_COLOR_FormatYUV420SemiPlanar,
43eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    OMX_COLOR_FormatAndroidOpaque
44eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni};
45eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
46eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nitemplate<class T>
47eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic void InitOMXParams(T *params) {
48eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    params->nSize = sizeof(T);
49eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    params->nVersion.s.nVersionMajor = 1;
50eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    params->nVersion.s.nVersionMinor = 0;
51eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    params->nVersion.s.nRevision = 0;
52eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    params->nVersion.s.nStep = 0;
53eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni}
54ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni
55ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang NiSoftVideoEncoderOMXComponent::SoftVideoEncoderOMXComponent(
56eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        const char *name,
57eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        const char *componentRole,
58eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        OMX_VIDEO_CODINGTYPE codingType,
59eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        const CodecProfileLevel *profileLevels,
60eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        size_t numProfileLevels,
61eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        int32_t width,
62eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        int32_t height,
63eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        const OMX_CALLBACKTYPE *callbacks,
64eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        OMX_PTR appData,
65eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        OMX_COMPONENTTYPE **component)
661ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    : SimpleSoftOMXComponent(name, callbacks, appData, component),
67eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni      mInputDataIsMeta(false),
68eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni      mWidth(width),
691ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni      mHeight(height),
70eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni      mBitrate(192000),
71eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni      mFramerate(30 << 16), // Q16 format
72eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni      mColorFormat(OMX_COLOR_FormatYUV420Planar),
73eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni      mMinOutputBufferSize(384), // arbitrary, using one uncompressed macroblock
74eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni      mMinCompressionRatio(1),   // max output size is normally the input size
75eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni      mComponentRole(componentRole),
76eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni      mCodingType(codingType),
771ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni      mProfileLevels(profileLevels),
78eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni      mNumProfileLevels(numProfileLevels) {
791ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni}
80eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
811ffd86b448d78366190c540f98f8b6d641cdb6cfYang Nivoid SoftVideoEncoderOMXComponent::initPorts(
821ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni        OMX_U32 numInputBuffers, OMX_U32 numOutputBuffers, OMX_U32 outputBufferSize,
83eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        const char *mime, OMX_U32 minCompressionRatio) {
84eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    OMX_PARAM_PORTDEFINITIONTYPE def;
851ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
861ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    mMinOutputBufferSize = outputBufferSize;
87da0f069871343119251d6b0586be356dc2146a62Yang Ni    mMinCompressionRatio = minCompressionRatio;
88da0f069871343119251d6b0586be356dc2146a62Yang Ni
89062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    InitOMXParams(&def);
90062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
91062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    def.nPortIndex = kInputPortIndex;
92062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    def.eDir = OMX_DirInput;
93062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    def.nBufferCountMin = numInputBuffers;
94da0f069871343119251d6b0586be356dc2146a62Yang Ni    def.nBufferCountActual = def.nBufferCountMin;
95eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    def.bEnabled = OMX_TRUE;
96eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    def.bPopulated = OMX_FALSE;
97eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    def.eDomain = OMX_PortDomainVideo;
98062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    def.bBuffersContiguous = OMX_FALSE;
99da0f069871343119251d6b0586be356dc2146a62Yang Ni    def.format.video.pNativeRender = NULL;
100da0f069871343119251d6b0586be356dc2146a62Yang Ni    def.format.video.nFrameWidth = mWidth;
101ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    def.format.video.nFrameHeight = mHeight;
102eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    def.format.video.nStride = def.format.video.nFrameWidth;
103eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    def.format.video.nSliceHeight = def.format.video.nFrameHeight;
104eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    def.format.video.nBitrate = 0;
105da0f069871343119251d6b0586be356dc2146a62Yang Ni    // frameRate is in Q16 format.
106ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    def.format.video.xFramerate = mFramerate;
107ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    def.format.video.bFlagErrorConcealment = OMX_FALSE;
108062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    def.nBufferAlignment = kInputBufferAlignment;
109eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    def.format.video.cMIMEType = const_cast<char *>("video/raw");
110eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
1111ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    def.format.video.eColorFormat = mColorFormat;
1121ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    def.format.video.pNativeWindow = NULL;
113eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    // buffersize set in updatePortParams
114ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni
115ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    addPort(def);
116ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni
117ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    InitOMXParams(&def);
118ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni
119ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    def.nPortIndex = kOutputPortIndex;
120ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    def.eDir = OMX_DirOutput;
121eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    def.nBufferCountMin = numOutputBuffers;
122ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    def.nBufferCountActual = def.nBufferCountMin;
123ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    def.bEnabled = OMX_TRUE;
124ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    def.bPopulated = OMX_FALSE;
125ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    def.eDomain = OMX_PortDomainVideo;
126ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    def.bBuffersContiguous = OMX_FALSE;
127ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    def.format.video.pNativeRender = NULL;
128eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    def.format.video.nFrameWidth = mWidth;
129eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    def.format.video.nFrameHeight = mHeight;
1301ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    def.format.video.nStride = 0;
1311ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    def.format.video.nSliceHeight = 0;
132ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    def.format.video.nBitrate = mBitrate;
133eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    def.format.video.xFramerate = 0 << 16;
1341ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    def.format.video.bFlagErrorConcealment = OMX_FALSE;
1351ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    def.nBufferAlignment = kOutputBufferAlignment;
1361ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    def.format.video.cMIMEType = const_cast<char *>(mime);
1371ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    def.format.video.eCompressionFormat = mCodingType;
138062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
139062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    def.format.video.pNativeWindow = NULL;
140eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    // buffersize set in updatePortParams
141eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
142062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    addPort(def);
143062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
144eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    updatePortParams();
145eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni}
146062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
147062c287f573ecc06c38ee4295e5627e12c52ac3dYang Nivoid SoftVideoEncoderOMXComponent::updatePortParams() {
148062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef;
149062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    inDef->format.video.nFrameWidth = mWidth;
150eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    inDef->format.video.nFrameHeight = mHeight;
151062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    inDef->format.video.nStride = inDef->format.video.nFrameWidth;
152062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    inDef->format.video.nSliceHeight = inDef->format.video.nFrameHeight;
153eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    inDef->format.video.xFramerate = mFramerate;
154eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    inDef->format.video.eColorFormat = mColorFormat;
155eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    uint32_t rawBufferSize =
1561ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni        inDef->format.video.nStride * inDef->format.video.nSliceHeight * 3 / 2;
157eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    if (inDef->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
158eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        inDef->nBufferSize = max(sizeof(VideoNativeMetadata), sizeof(VideoGrallocMetadata));
159062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    } else {
160062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        inDef->nBufferSize = rawBufferSize;
161062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
162eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
163da0f069871343119251d6b0586be356dc2146a62Yang Ni    OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef;
164eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    outDef->format.video.nFrameWidth = mWidth;
165eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    outDef->format.video.nFrameHeight = mHeight;
166da0f069871343119251d6b0586be356dc2146a62Yang Ni    outDef->format.video.nBitrate = mBitrate;
167eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
168eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    outDef->nBufferSize = max(mMinOutputBufferSize, rawBufferSize / mMinCompressionRatio);
169da0f069871343119251d6b0586be356dc2146a62Yang Ni}
170da0f069871343119251d6b0586be356dc2146a62Yang Ni
171062c287f573ecc06c38ee4295e5627e12c52ac3dYang NiOMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalSetPortParams(
172062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        const OMX_PARAM_PORTDEFINITIONTYPE *port) {
173062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    if (port->nPortIndex == kInputPortIndex) {
174062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        mWidth = port->format.video.nFrameWidth;
175062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        mHeight = port->format.video.nFrameHeight;
176eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
177062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        // xFramerate comes in Q16 format, in frames per second unit
178062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        mFramerate = port->format.video.xFramerate;
179062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
180062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        if (port->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused
181062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                || (port->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar
182062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                        && port->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar
183062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                        && port->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) {
184062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            return OMX_ErrorUnsupportedSetting;
185062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        }
186062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
1871ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni        mColorFormat = port->format.video.eColorFormat;
1881ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    } else if (port->nPortIndex == kOutputPortIndex) {
1891ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni        if (port->format.video.eCompressionFormat != mCodingType
190eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                || port->format.video.eColorFormat != OMX_COLOR_FormatUnused) {
191eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            return OMX_ErrorUnsupportedSetting;
192eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        }
193062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
194062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        mBitrate = port->format.video.nBitrate;
195062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    } else {
196062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        return OMX_ErrorBadPortIndex;
197062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
198da0f069871343119251d6b0586be356dc2146a62Yang Ni
199da0f069871343119251d6b0586be356dc2146a62Yang Ni    updatePortParams();
200da0f069871343119251d6b0586be356dc2146a62Yang Ni    return OMX_ErrorNone;
201da0f069871343119251d6b0586be356dc2146a62Yang Ni}
202da0f069871343119251d6b0586be356dc2146a62Yang Ni
203da0f069871343119251d6b0586be356dc2146a62Yang NiOMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalSetParameter(
204edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        OMX_INDEXTYPE index, const OMX_PTR param) {
205edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    // can include extension index OMX_INDEXEXTTYPE
206edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    const int32_t indexFull = index;
207edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni
208edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    switch (indexFull) {
209edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        case OMX_IndexParamVideoErrorCorrection:
210edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        {
211edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni            return OMX_ErrorNotImplemented;
212edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        }
213edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni
214edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        case OMX_IndexParamStandardComponentRole:
215edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        {
216edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
217edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni                (const OMX_PARAM_COMPONENTROLETYPE *)param;
218edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni
219edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni            if (strncmp((const char *)roleParams->cRole,
220edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni                        mComponentRole,
221edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni                        OMX_MAX_STRINGNAME_SIZE - 1)) {
222edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni                return OMX_ErrorUnsupportedSetting;
223edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni            }
224edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni
225edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni            return OMX_ErrorNone;
226edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        }
227edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni
228edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        case OMX_IndexParamPortDefinition:
229edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        {
230da0f069871343119251d6b0586be356dc2146a62Yang Ni            OMX_ERRORTYPE err = internalSetPortParams((const OMX_PARAM_PORTDEFINITIONTYPE *)param);
231eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
232eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            if (err != OMX_ErrorNone) {
233da0f069871343119251d6b0586be356dc2146a62Yang Ni                return err;
234da0f069871343119251d6b0586be356dc2146a62Yang Ni            }
235da0f069871343119251d6b0586be356dc2146a62Yang Ni
236062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            return SimpleSoftOMXComponent::internalSetParameter(index, param);
237062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        }
238eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
239edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        case OMX_IndexParamVideoPortFormat:
240edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        {
241eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            const OMX_VIDEO_PARAM_PORTFORMATTYPE* format =
242eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param;
243eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
244eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            if (format->nPortIndex == kInputPortIndex) {
245eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                if (format->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
246eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
247edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni                    format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
248edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni                    mColorFormat = format->eColorFormat;
249edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni
250eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    updatePortParams();
251eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    return OMX_ErrorNone;
252eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                } else {
253062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    ALOGE("Unsupported color format %i", format->eColorFormat);
254062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    return OMX_ErrorUnsupportedSetting;
255062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                }
256062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            } else if (format->nPortIndex == kOutputPortIndex) {
257062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                if (format->eCompressionFormat == mCodingType) {
258062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    return OMX_ErrorNone;
259062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                } else {
260eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    return OMX_ErrorUnsupportedSetting;
261eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                }
262eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            } else {
263eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                return OMX_ErrorBadPortIndex;
264eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            }
265eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        }
266da0f069871343119251d6b0586be356dc2146a62Yang Ni
267da0f069871343119251d6b0586be356dc2146a62Yang Ni        case kStoreMetaDataExtensionIndex:
268da0f069871343119251d6b0586be356dc2146a62Yang Ni        {
269da0f069871343119251d6b0586be356dc2146a62Yang Ni            // storeMetaDataInBuffers
270eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            const StoreMetaDataInBuffersParams *storeParam =
271da0f069871343119251d6b0586be356dc2146a62Yang Ni                (const StoreMetaDataInBuffersParams *)param;
272eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
273eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            if (storeParam->nPortIndex == kOutputPortIndex) {
274eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                return storeParam->bStoreMetaData ? OMX_ErrorUnsupportedSetting : OMX_ErrorNone;
275eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            } else if (storeParam->nPortIndex != kInputPortIndex) {
276da0f069871343119251d6b0586be356dc2146a62Yang Ni                return OMX_ErrorBadPortIndex;
277eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            }
278eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
279eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            mInputDataIsMeta = (storeParam->bStoreMetaData == OMX_TRUE);
280eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            if (mInputDataIsMeta) {
281da0f069871343119251d6b0586be356dc2146a62Yang Ni                mColorFormat = OMX_COLOR_FormatAndroidOpaque;
282eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            } else if (mColorFormat == OMX_COLOR_FormatAndroidOpaque) {
283eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                mColorFormat = OMX_COLOR_FormatYUV420Planar;
284eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            }
285eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            updatePortParams();
286da0f069871343119251d6b0586be356dc2146a62Yang Ni            return OMX_ErrorNone;
287eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        }
288eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
289eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        default:
290eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            return SimpleSoftOMXComponent::internalSetParameter(index, param);
291eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    }
292eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni}
293da0f069871343119251d6b0586be356dc2146a62Yang Ni
294eb9aa675754c49f613c6ad71d41472b30f38b007Yang NiOMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalGetParameter(
295eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        OMX_INDEXTYPE index, OMX_PTR param) {
296eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    switch ((int)index) {
297eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        case OMX_IndexParamVideoErrorCorrection:
298da0f069871343119251d6b0586be356dc2146a62Yang Ni        {
299eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            return OMX_ErrorNotImplemented;
300da0f069871343119251d6b0586be356dc2146a62Yang Ni        }
301062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
302062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        case OMX_IndexParamVideoPortFormat:
303062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        {
304062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
305062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)param;
306062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
307062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            if (formatParams->nPortIndex == kInputPortIndex) {
308062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                if (formatParams->nIndex >= NELEM(kSupportedColorFormats)) {
309062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    return OMX_ErrorNoMore;
310062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                }
311062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
312062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                // Color formats, in order of preference
313062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                formatParams->eColorFormat = kSupportedColorFormats[formatParams->nIndex];
314062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
315062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                formatParams->xFramerate = mFramerate;
316062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                return OMX_ErrorNone;
317062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            } else if (formatParams->nPortIndex == kOutputPortIndex) {
318062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                formatParams->eCompressionFormat = mCodingType;
319062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
320062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                formatParams->xFramerate = 0;
321da0f069871343119251d6b0586be356dc2146a62Yang Ni                return OMX_ErrorNone;
322da0f069871343119251d6b0586be356dc2146a62Yang Ni            } else {
323da0f069871343119251d6b0586be356dc2146a62Yang Ni                return OMX_ErrorBadPortIndex;
324062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            }
325da0f069871343119251d6b0586be356dc2146a62Yang Ni        }
326062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
327eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        case OMX_IndexParamVideoProfileLevelQuerySupported:
328eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        {
329da0f069871343119251d6b0586be356dc2146a62Yang Ni            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel =
330eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                  (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) param;
331eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
332eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            if (profileLevel->nPortIndex != kOutputPortIndex) {
333da0f069871343119251d6b0586be356dc2146a62Yang Ni                ALOGE("Invalid port index: %u", profileLevel->nPortIndex);
334062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                return OMX_ErrorUnsupportedIndex;
335062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            }
336062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
337da0f069871343119251d6b0586be356dc2146a62Yang Ni            if (profileLevel->nProfileIndex >= mNumProfileLevels) {
338062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                return OMX_ErrorNoMore;
339eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            }
340eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
341eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            profileLevel->eProfile = mProfileLevels[profileLevel->nProfileIndex].mProfile;
342da0f069871343119251d6b0586be356dc2146a62Yang Ni            profileLevel->eLevel   = mProfileLevels[profileLevel->nProfileIndex].mLevel;
343eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            return OMX_ErrorNone;
344eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        }
345eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
346062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        case OMX_IndexParamConsumerUsageBits:
347062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        {
348062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            OMX_U32 *usageBits = (OMX_U32 *)param;
349062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            *usageBits = GRALLOC_USAGE_SW_READ_OFTEN;
350062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            return OMX_ErrorNone;
351062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        }
352062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
353062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        default:
354062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            return SimpleSoftOMXComponent::internalGetParameter(index, param);
355062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
356062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni}
357da0f069871343119251d6b0586be356dc2146a62Yang Ni
358062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni// static
359062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni__attribute__((no_sanitize("integer")))
360062c287f573ecc06c38ee4295e5627e12c52ac3dYang Nivoid SoftVideoEncoderOMXComponent::ConvertFlexYUVToPlanar(
361062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        uint8_t *dst, size_t dstStride, size_t dstVStride,
362062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        struct android_ycbcr *ycbcr, int32_t width, int32_t height) {
363062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    const uint8_t *src = (const uint8_t *)ycbcr->y;
364062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    const uint8_t *srcU = (const uint8_t *)ycbcr->cb;
365062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    const uint8_t *srcV = (const uint8_t *)ycbcr->cr;
366062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    uint8_t *dstU = dst + dstVStride * dstStride;
367062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    uint8_t *dstV = dstU + (dstVStride >> 1) * (dstStride >> 1);
368062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
369062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    for (size_t y = height; y > 0; --y) {
370062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        memcpy(dst, src, width);
371eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        dst += dstStride;
372da0f069871343119251d6b0586be356dc2146a62Yang Ni        src += ycbcr->ystride;
373433558f0f9abbf07770db288183a15fd261cace2Yabin Cui    }
374433558f0f9abbf07770db288183a15fd261cace2Yabin Cui    if (ycbcr->cstride == ycbcr->ystride >> 1 && ycbcr->chroma_step == 1) {
375433558f0f9abbf07770db288183a15fd261cace2Yabin Cui        // planar
376433558f0f9abbf07770db288183a15fd261cace2Yabin Cui        for (size_t y = height >> 1; y > 0; --y) {
377433558f0f9abbf07770db288183a15fd261cace2Yabin Cui            memcpy(dstU, srcU, width >> 1);
378433558f0f9abbf07770db288183a15fd261cace2Yabin Cui            dstU += dstStride >> 1;
379433558f0f9abbf07770db288183a15fd261cace2Yabin Cui            srcU += ycbcr->cstride;
380433558f0f9abbf07770db288183a15fd261cace2Yabin Cui            memcpy(dstV, srcV, width >> 1);
381433558f0f9abbf07770db288183a15fd261cace2Yabin Cui            dstV += dstStride >> 1;
382433558f0f9abbf07770db288183a15fd261cace2Yabin Cui            srcV += ycbcr->cstride;
383433558f0f9abbf07770db288183a15fd261cace2Yabin Cui        }
384edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    } else {
385edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        // arbitrary
386edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        for (size_t y = height >> 1; y > 0; --y) {
387eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            for (size_t x = width >> 1; x > 0; --x) {
388062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                *dstU++ = *srcU;
389edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni                *dstV++ = *srcV;
3902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                srcU += ycbcr->chroma_step;
3912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                srcV += ycbcr->chroma_step;
3922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni            }
393eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            dstU += (dstStride >> 1) - (width >> 1);
394eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            dstV += (dstStride >> 1) - (width >> 1);
395433558f0f9abbf07770db288183a15fd261cace2Yabin Cui            srcU += ycbcr->cstride - (width >> 1) * ycbcr->chroma_step;
396eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            srcV += ycbcr->cstride - (width >> 1) * ycbcr->chroma_step;
397eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        }
398da0f069871343119251d6b0586be356dc2146a62Yang Ni    }
399eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni}
400eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
401eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni// static
402da0f069871343119251d6b0586be356dc2146a62Yang Ni__attribute__((no_sanitize("integer")))
403eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nivoid SoftVideoEncoderOMXComponent::ConvertYUV420SemiPlanarToYUV420Planar(
404da0f069871343119251d6b0586be356dc2146a62Yang Ni        const uint8_t *inYVU, uint8_t* outYUV, int32_t width, int32_t height) {
405eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    // TODO: add support for stride
406eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    int32_t outYsize = width * height;
407eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    uint32_t *outY  = (uint32_t *) outYUV;
408eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    uint16_t *outCb = (uint16_t *) (outYUV + outYsize);
409da0f069871343119251d6b0586be356dc2146a62Yang Ni    uint16_t *outCr = (uint16_t *) (outYUV + outYsize + (outYsize >> 2));
410062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
411062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    /* Y copying */
412eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    memcpy(outY, inYVU, outYsize);
413eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
414eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    /* U & V copying */
415da0f069871343119251d6b0586be356dc2146a62Yang Ni    // FIXME this only works if width is multiple of 4
416eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    uint32_t *inYVU_4 = (uint32_t *) (inYVU + outYsize);
417062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    for (int32_t i = height >> 1; i > 0; --i) {
418062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        for (int32_t j = width >> 2; j > 0; --j) {
419da0f069871343119251d6b0586be356dc2146a62Yang Ni            uint32_t temp = *inYVU_4++;
420da0f069871343119251d6b0586be356dc2146a62Yang Ni            uint32_t tempU = temp & 0xFF;
4211ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni            tempU = tempU | ((temp >> 8) & 0xFF00);
4221ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
4231ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni            uint32_t tempV = (temp >> 8) & 0xFF;
424eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            tempV = tempV | ((temp >> 16) & 0xFF00);
425eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
426eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            *outCb++ = tempU;
427eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            *outCr++ = tempV;
4281ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni        }
4291ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    }
430da0f069871343119251d6b0586be356dc2146a62Yang Ni}
431eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
432eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni// static
433062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni__attribute__((no_sanitize("integer")))
434062c287f573ecc06c38ee4295e5627e12c52ac3dYang Nivoid SoftVideoEncoderOMXComponent::ConvertRGB32ToPlanar(
435eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        uint8_t *dstY, size_t dstStride, size_t dstVStride,
436eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        const uint8_t *src, size_t width, size_t height, size_t srcStride,
437eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        bool bgr) {
438eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    CHECK((width & 1) == 0);
439eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    CHECK((height & 1) == 0);
440eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
441eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    uint8_t *dstU = dstY + dstStride * dstVStride;
442eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    uint8_t *dstV = dstU + (dstStride >> 1) * (dstVStride >> 1);
443eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
444eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni#ifdef SURFACE_IS_BGR32
445ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    bgr = !bgr;
446ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni#endif
447ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni
448062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    const size_t redOffset   = bgr ? 2 : 0;
449062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    const size_t greenOffset = 1;
450062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    const size_t blueOffset  = bgr ? 0 : 2;
451062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
452062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    for (size_t y = 0; y < height; ++y) {
453062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        for (size_t x = 0; x < width; ++x) {
454062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            unsigned red   = src[redOffset];
455062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            unsigned green = src[greenOffset];
456062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            unsigned blue  = src[blueOffset];
457062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
458062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            // using ITU-R BT.601 conversion matrix
459062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            unsigned luma =
460062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                ((red * 66 + green * 129 + blue * 25) >> 8) + 16;
461062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
462eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            dstY[x] = luma;
463062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
464062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            if ((x & 1) == 0 && (y & 1) == 0) {
465062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                unsigned U =
466062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    ((-red * 38 - green * 74 + blue * 112) >> 8) + 128;
467062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
468062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                unsigned V =
469eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    ((red * 112 - green * 94 - blue * 18) >> 8) + 128;
470eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
4711ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni                dstU[x >> 1] = U;
4721ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni                dstV[x >> 1] = V;
4731ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni            }
474da0f069871343119251d6b0586be356dc2146a62Yang Ni            src += 4;
475062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        }
476062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
477062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        if ((y & 1) == 0) {
478062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            dstU += dstStride >> 1;
479062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            dstV += dstStride >> 1;
480062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        }
481062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
482062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        src += srcStride - 4 * width;
483062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        dstY += dstStride;
484062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
485062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni}
486062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
487062c287f573ecc06c38ee4295e5627e12c52ac3dYang Niconst uint8_t *SoftVideoEncoderOMXComponent::extractGraphicBuffer(
488062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        uint8_t *dst, size_t dstSize,
489062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        const uint8_t *src, size_t srcSize,
490062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        size_t width, size_t height) const {
491062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    size_t dstStride = width;
492062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    size_t dstVStride = height;
493062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
494062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    MetadataBufferType bufferType = *(MetadataBufferType *)src;
495062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    bool usingANWBuffer = bufferType == kMetadataBufferTypeANWBuffer;
496eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    if (!usingANWBuffer && bufferType != kMetadataBufferTypeGrallocSource) {
497eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        ALOGE("Unsupported metadata type (%d)", bufferType);
498eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        return NULL;
499eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    }
500eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
501ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    buffer_handle_t handle;
502ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    int format;
503eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    size_t srcStride;
504eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    size_t srcVStride;
505eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    if (usingANWBuffer) {
506eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        if (srcSize < sizeof(VideoNativeMetadata)) {
507eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            ALOGE("Metadata is too small (%zu vs %zu)", srcSize, sizeof(VideoNativeMetadata));
508062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            return NULL;
509eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        }
510eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
511ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni        VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)src;
512ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni        ANativeWindowBuffer *buffer = nativeMeta.pBuffer;
513eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        handle = buffer->handle;
514eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        format = buffer->format;
515eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        srcStride = buffer->stride;
516eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        srcVStride = buffer->height;
517eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        // convert stride from pixels to bytes
518eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        if (format != HAL_PIXEL_FORMAT_YV12 &&
519eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            format != HAL_PIXEL_FORMAT_YCbCr_420_888) {
520eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            // TODO do we need to support other formats?
521062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            srcStride *= 4;
522062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        }
523eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
524ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni        if (nativeMeta.nFenceFd >= 0) {
525ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni            sp<Fence> fence = new Fence(nativeMeta.nFenceFd);
526062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            nativeMeta.nFenceFd = -1;
527eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            status_t err = fence->wait(IOMX::kFenceTimeoutMs);
528da0f069871343119251d6b0586be356dc2146a62Yang Ni            if (err != OK) {
529eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                ALOGE("Timed out waiting on input fence");
530eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                return NULL;
531eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            }
532da0f069871343119251d6b0586be356dc2146a62Yang Ni        }
533ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    } else {
534ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni        // TODO: remove this part.  Check if anyone uses this.
535eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
536eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        if (srcSize < sizeof(VideoGrallocMetadata)) {
537da0f069871343119251d6b0586be356dc2146a62Yang Ni            ALOGE("Metadata is too small (%zu vs %zu)", srcSize, sizeof(VideoGrallocMetadata));
538eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            return NULL;
539eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        }
540eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
541da0f069871343119251d6b0586be356dc2146a62Yang Ni        VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)(src);
542eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        handle = grallocMeta.pHandle;
543eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        // assume HAL_PIXEL_FORMAT_RGBA_8888
544eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        // there is no way to get the src stride without the graphic buffer
545eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        format = HAL_PIXEL_FORMAT_RGBA_8888;
546eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        srcStride = width * 4;
547062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        srcVStride = height;
548062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
549eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
550ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    size_t neededSize =
551ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni        dstStride * dstVStride + (width >> 1)
552eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                + (dstStride >> 1) * ((dstVStride >> 1) + (height >> 1) - 1);
553eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    if (dstSize < neededSize) {
5541ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni        ALOGE("destination buffer is too small (%zu vs %zu)", dstSize, neededSize);
5551ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni        return NULL;
5561ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    }
5571ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
558    auto& mapper = GraphicBufferMapper::get();
559
560    void *bits = NULL;
561    struct android_ycbcr ycbcr;
562    status_t res;
563    if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
564        res = mapper.lockYCbCr(
565                 handle,
566                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER,
567                 Rect(width, height), &ycbcr);
568    } else {
569        res = mapper.lock(
570                 handle,
571                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER,
572                 Rect(width, height), &bits);
573    }
574    if (res != OK) {
575        ALOGE("Unable to lock image buffer %p for access", handle);
576        return NULL;
577    }
578
579    switch (format) {
580        case HAL_PIXEL_FORMAT_YV12:  // YCrCb / YVU planar
581            // convert to flex YUV
582            ycbcr.y = bits;
583            ycbcr.cr = (uint8_t *)bits + srcStride * srcVStride;
584            ycbcr.cb = (uint8_t *)ycbcr.cr + (srcStride >> 1) * (srcVStride >> 1);
585            ycbcr.chroma_step = 1;
586            ycbcr.cstride = srcVStride >> 1;
587            ycbcr.ystride = srcVStride;
588            ConvertFlexYUVToPlanar(dst, dstStride, dstVStride, &ycbcr, width, height);
589            break;
590        case HAL_PIXEL_FORMAT_YCrCb_420_SP:  // YCrCb / YVU semiplanar, NV21
591            // convert to flex YUV
592            ycbcr.y = bits;
593            ycbcr.cr = (uint8_t *)bits + srcStride * srcVStride;
594            ycbcr.cb = (uint8_t *)ycbcr.cr + 1;
595            ycbcr.chroma_step = 2;
596            ycbcr.cstride = srcVStride;
597            ycbcr.ystride = srcVStride;
598            ConvertFlexYUVToPlanar(dst, dstStride, dstVStride, &ycbcr, width, height);
599            break;
600        case HAL_PIXEL_FORMAT_YCbCr_420_888:
601            ConvertFlexYUVToPlanar(dst, dstStride, dstVStride, &ycbcr, width, height);
602            break;
603        case HAL_PIXEL_FORMAT_RGBA_8888:
604        case HAL_PIXEL_FORMAT_BGRA_8888:
605            ConvertRGB32ToPlanar(
606                    dst, dstStride, dstVStride,
607                    (const uint8_t *)bits, width, height, srcStride,
608                    format == HAL_PIXEL_FORMAT_BGRA_8888);
609            break;
610        default:
611            ALOGE("Unsupported pixel format %#x", format);
612            dst = NULL;
613            break;
614    }
615
616    if (mapper.unlock(handle) != OK) {
617        ALOGE("Unable to unlock image buffer %p for access", handle);
618    }
619
620    return dst;
621}
622
623OMX_ERRORTYPE SoftVideoEncoderOMXComponent::getExtensionIndex(
624        const char *name, OMX_INDEXTYPE *index) {
625    if (!strcmp(name, "OMX.google.android.index.storeMetaDataInBuffers") ||
626        !strcmp(name, "OMX.google.android.index.storeANWBufferInMetadata")) {
627        *(int32_t*)index = kStoreMetaDataExtensionIndex;
628        return OMX_ErrorNone;
629    }
630    return SimpleSoftOMXComponent::getExtensionIndex(name, index);
631}
632
633}  // namespace android
634