SoftVPXEncoder.cpp revision e5b67490353efa67496d1c907edaab0cf5a41d2e
1ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi/*
2ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * Copyright (C) 2013 The Android Open Source Project
3ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi *
4ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
5ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * you may not use this file except in compliance with the License.
6ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * You may obtain a copy of the License at
7ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi *
8ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
9ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi *
10ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
11ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
12ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * See the License for the specific language governing permissions and
14ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi * limitations under the License.
15ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi */
16ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
177126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten// #define LOG_NDEBUG 0
187126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#define LOG_TAG "SoftVPXEncoder"
197126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include "SoftVPXEncoder.h"
207126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
217126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <utils/Log.h>
227126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
237126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <media/hardware/HardwareAPI.h>
247126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <media/hardware/MetadataBufferType.h>
257126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <media/stagefright/foundation/ADebug.h>
267126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#include <media/stagefright/MediaDefs.h>
277126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
287126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#ifndef INT32_MAX
297126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#define INT32_MAX   2147483647
307126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten#endif
317126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
327126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastennamespace android {
337126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten
347126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastentemplate<class T>
357126c25d7c037e5086216cf540ecf40779c3585aGlenn Kastenstatic void InitOMXParams(T *params) {
367126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    params->nSize = sizeof(T);
377126c25d7c037e5086216cf540ecf40779c3585aGlenn Kasten    // OMX IL 1.1.2
38ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    params->nVersion.s.nVersionMajor = 1;
39ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    params->nVersion.s.nVersionMinor = 1;
40ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    params->nVersion.s.nRevision = 2;
41ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    params->nVersion.s.nStep = 0;
42ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi}
43ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
44ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
45ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivistatic int GetCPUCoreCount() {
46ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    int cpuCoreCount = 1;
47b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi#if defined(_SC_NPROCESSORS_ONLN)
48ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
4901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten#else
50b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    // _SC_NPROC_ONLN must be defined...
51b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    cpuCoreCount = sysconf(_SC_NPROC_ONLN);
52ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi#endif
53ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    CHECK_GE(cpuCoreCount, 1);
54ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    return cpuCoreCount;
55ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi}
56ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
57a384948fc96e81947a9b689fc65ea0e7b93df25cJean-Michel TriviSoftVPXEncoder::SoftVPXEncoder(const char *name,
58ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi                               const OMX_CALLBACKTYPE *callbacks,
59ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi                               OMX_PTR appData,
60ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi                               OMX_COMPONENTTYPE **component)
61ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    : SoftVideoEncoderOMXComponent(name, callbacks, appData, component),
62ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mCodecContext(NULL),
63ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mCodecConfiguration(NULL),
64ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mCodecInterface(NULL),
65ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mWidth(176),
66ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mHeight(144),
67ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mBitrate(192000),  // in bps
68ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mFramerate(30 << 16), // in Q16 format
69ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mBitrateUpdated(false),
70ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mBitrateControlMode(VPX_VBR),  // variable bitrate
71ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mDCTPartitions(0),
72ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mErrorResilience(OMX_FALSE),
73c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten      mColorFormat(OMX_COLOR_FormatYUV420Planar),
74ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mLevel(OMX_VIDEO_VP8Level_Version0),
75ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mKeyFrameInterval(0),
76ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mMinQuantizer(0),
77ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mMaxQuantizer(0),
78ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mTemporalLayers(0),
79ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mTemporalPatternType(OMX_VIDEO_VPXTemporalLayerPatternNone),
80ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mTemporalPatternLength(0),
81ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mTemporalPatternIdx(0),
82ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mLastTimestamp(0x7FFFFFFFFFFFFFFFLL),
83ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mConversionBuffer(NULL),
84ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mInputDataIsMeta(false),
85ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi      mKeyFrameRequested(false) {
869bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi    memset(mTemporalLayerBitrateRatio, 0, sizeof(mTemporalLayerBitrateRatio));
879bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi    mTemporalLayerBitrateRatio[0] = 100;
889bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi    initPorts();
899bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi}
909bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi
919bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi
929bc234ed758273259e334144cc6e1643b2494175Jean-Michel TriviSoftVPXEncoder::~SoftVPXEncoder() {
939bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi    releaseEncoder();
949bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi}
959bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi
969bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi
979bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivivoid SoftVPXEncoder::initPorts() {
989bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi    OMX_PARAM_PORTDEFINITIONTYPE inputPort;
999bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi    OMX_PARAM_PORTDEFINITIONTYPE outputPort;
1009bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi
1019bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi    InitOMXParams(&inputPort);
1029bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi    InitOMXParams(&outputPort);
1039bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi
1049bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi    inputPort.nBufferCountMin = kNumBuffers;
1059bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi    inputPort.nBufferCountActual = inputPort.nBufferCountMin;
1069bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi    inputPort.bEnabled = OMX_TRUE;
107ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.bPopulated = OMX_FALSE;
108ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.eDomain = OMX_PortDomainVideo;
109ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.bBuffersContiguous = OMX_FALSE;
11001e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    inputPort.format.video.pNativeRender = NULL;
111ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.format.video.nFrameWidth = mWidth;
112ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.format.video.nFrameHeight = mHeight;
11304c7354b8a9afcf2151c00c1dfbc64d0ba5d33ccGlenn Kasten    inputPort.format.video.nStride = inputPort.format.video.nFrameWidth;
114ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.format.video.nSliceHeight = inputPort.format.video.nFrameHeight;
115ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.format.video.nBitrate = 0;
116ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    // frameRate is in Q16 format.
117ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.format.video.xFramerate = mFramerate;
118ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.format.video.bFlagErrorConcealment = OMX_FALSE;
119ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.nPortIndex = kInputPortIndex;
120ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.eDir = OMX_DirInput;
121ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.nBufferAlignment = kInputBufferAlignment;
122ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.format.video.cMIMEType =
123ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
124ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
125ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.format.video.eColorFormat = mColorFormat;
126ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.format.video.pNativeWindow = NULL;
127ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    inputPort.nBufferSize =
128ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        (inputPort.format.video.nStride *
12901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten        inputPort.format.video.nSliceHeight * 3) / 2;
130ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
131ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    addPort(inputPort);
13204c7354b8a9afcf2151c00c1dfbc64d0ba5d33ccGlenn Kasten
133ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.nBufferCountMin = kNumBuffers;
13404c7354b8a9afcf2151c00c1dfbc64d0ba5d33ccGlenn Kasten    outputPort.nBufferCountActual = outputPort.nBufferCountMin;
135ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.bEnabled = OMX_TRUE;
136ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.bPopulated = OMX_FALSE;
137ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.eDomain = OMX_PortDomainVideo;
138ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.bBuffersContiguous = OMX_FALSE;
139ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.format.video.pNativeRender = NULL;
140ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.format.video.nFrameWidth = mWidth;
141ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.format.video.nFrameHeight = mHeight;
142ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.format.video.nStride = outputPort.format.video.nFrameWidth;
143ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.format.video.nSliceHeight = outputPort.format.video.nFrameHeight;
144ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.format.video.nBitrate = mBitrate;
145ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.format.video.xFramerate = 0;
146ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.format.video.bFlagErrorConcealment = OMX_FALSE;
147ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.nPortIndex = kOutputPortIndex;
148ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.eDir = OMX_DirOutput;
149ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.nBufferAlignment = kOutputBufferAlignment;
150ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.format.video.cMIMEType =
151ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VP8);
152ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.format.video.eCompressionFormat = OMX_VIDEO_CodingVP8;
153ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    outputPort.format.video.eColorFormat = OMX_COLOR_FormatUnused;
15401e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    outputPort.format.video.pNativeWindow = NULL;
155b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    outputPort.nBufferSize = 1024 * 1024; // arbitrary
156b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
157ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    addPort(outputPort);
158ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi}
159ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
160ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
161ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivistatus_t SoftVPXEncoder::initEncoder() {
162ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    vpx_codec_err_t codec_return;
163ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
16401e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    mCodecContext = new vpx_codec_ctx_t;
165ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    mCodecConfiguration = new vpx_codec_enc_cfg_t;
166ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    mCodecInterface = vpx_codec_vp8_cx();
167ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
168ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    if (mCodecInterface == NULL) {
169ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        return UNKNOWN_ERROR;
170ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    }
171ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    ALOGD("VP8: initEncoder. BRMode: %u. TSLayers: %zu. KF: %u. QP: %u - %u",
172ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi          (uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval,
173ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi          mMinQuantizer, mMaxQuantizer);
174ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    codec_return = vpx_codec_enc_config_default(mCodecInterface,
175ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi                                                mCodecConfiguration,
176ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi                                                0);  // Codec specific flags
177ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
178ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    if (codec_return != VPX_CODEC_OK) {
179ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        ALOGE("Error populating default configuration for vpx encoder.");
180ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        return UNKNOWN_ERROR;
181ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    }
182ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
183ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    mCodecConfiguration->g_w = mWidth;
18401e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    mCodecConfiguration->g_h = mHeight;
185ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    mCodecConfiguration->g_threads = GetCPUCoreCount();
18601e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten    mCodecConfiguration->g_error_resilient = mErrorResilience;
187b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
188b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    switch (mLevel) {
189ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        case OMX_VIDEO_VP8Level_Version0:
190ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->g_profile = 0;
191ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            break;
192ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
193ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        case OMX_VIDEO_VP8Level_Version1:
194ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->g_profile = 1;
195ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            break;
1962246c698482ab6860906672229f0ae6d886e6302Glenn Kasten
197ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        case OMX_VIDEO_VP8Level_Version2:
198ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->g_profile = 2;
19901e9f5fa4698856f92bcfd88188ee4c8397b22dbGlenn Kasten            break;
200ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
201ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        case OMX_VIDEO_VP8Level_Version3:
202ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->g_profile = 3;
203ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            break;
204ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
205ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        default:
206ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->g_profile = 0;
207ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    }
208ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
209ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    // OMX timebase unit is microsecond
210ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    // g_timebase is in seconds (i.e. 1/1000000 seconds)
211ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    mCodecConfiguration->g_timebase.num = 1;
212ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    mCodecConfiguration->g_timebase.den = 1000000;
213ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    // rc_target_bitrate is in kbps, mBitrate in bps
214b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    mCodecConfiguration->rc_target_bitrate = (mBitrate + 500) / 1000;
215b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    mCodecConfiguration->rc_end_usage = mBitrateControlMode;
216ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    // Disable frame drop - not allowed in MediaCodec now.
217ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    mCodecConfiguration->rc_dropframe_thresh = 0;
218ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    if (mBitrateControlMode == VPX_CBR) {
219b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // Disable spatial resizing.
220b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        mCodecConfiguration->rc_resize_allowed = 0;
221b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // Single-pass mode.
222b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        mCodecConfiguration->g_pass = VPX_RC_ONE_PASS;
223b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // Maximum amount of bits that can be subtracted from the target
224b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // bitrate - expressed as percentage of the target bitrate.
225b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        mCodecConfiguration->rc_undershoot_pct = 100;
226b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // Maximum amount of bits that can be added to the target
227b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // bitrate - expressed as percentage of the target bitrate.
228b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        mCodecConfiguration->rc_overshoot_pct = 15;
229b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // Initial value of the buffer level in ms.
230b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        mCodecConfiguration->rc_buf_initial_sz = 500;
231b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // Amount of data that the encoder should try to maintain in ms.
232b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        mCodecConfiguration->rc_buf_optimal_sz = 600;
233b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // The amount of data that may be buffered by the decoding
234b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // application in ms.
235b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        mCodecConfiguration->rc_buf_sz = 1000;
236b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // Enable error resilience - needed for packet loss.
237b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        mCodecConfiguration->g_error_resilient = 1;
238b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // Disable lagged encoding.
239b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        mCodecConfiguration->g_lag_in_frames = 0;
240ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        // Maximum key frame interval - for CBR boost to 3000
241ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        mCodecConfiguration->kf_max_dist = 3000;
242ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        // Encoder determines optimal key frame placement automatically.
243ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        mCodecConfiguration->kf_mode = VPX_KF_AUTO;
244ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    }
245ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
246ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    // Frames temporal pattern - for now WebRTC like pattern is only supported.
247ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    switch (mTemporalLayers) {
248ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        case 0:
2499bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi        {
2509bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi            mTemporalPatternLength = 0;
2519bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi            break;
2529bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi        }
2539bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi        case 1:
2549bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi        {
2559bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi            mCodecConfiguration->ts_number_layers = 1;
2569bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi            mCodecConfiguration->ts_rate_decimator[0] = 1;
2579bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi            mCodecConfiguration->ts_periodicity = 1;
2589bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi            mCodecConfiguration->ts_layer_id[0] = 0;
2599bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi            mTemporalPattern[0] = kTemporalUpdateLastRefAll;
2609bc234ed758273259e334144cc6e1643b2494175Jean-Michel Trivi            mTemporalPatternLength = 1;
261ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            break;
2625e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        }
2635e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        case 2:
264ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        {
265ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_number_layers = 2;
266ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_rate_decimator[0] = 2;
267ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_rate_decimator[1] = 1;
268ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_periodicity = 2;
269ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_layer_id[0] = 0;
270ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_layer_id[1] = 1;
271ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[0] = kTemporalUpdateLastAndGoldenRefAltRef;
272ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[1] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
273ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[2] = kTemporalUpdateLastRefAltRef;
274ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[3] = kTemporalUpdateGoldenRefAltRef;
275ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[4] = kTemporalUpdateLastRefAltRef;
276ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[5] = kTemporalUpdateGoldenRefAltRef;
277ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[6] = kTemporalUpdateLastRefAltRef;
278ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[7] = kTemporalUpdateNone;
279ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPatternLength = 8;
280ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            break;
281ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        }
282ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        case 3:
283ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        {
284ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_number_layers = 3;
285ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_rate_decimator[0] = 4;
286ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_rate_decimator[1] = 2;
287ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_rate_decimator[2] = 1;
288ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_periodicity = 4;
289ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_layer_id[0] = 0;
290ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_layer_id[1] = 2;
291ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_layer_id[2] = 1;
292ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->ts_layer_id[3] = 2;
293ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[0] = kTemporalUpdateLastAndGoldenRefAltRef;
294ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[1] = kTemporalUpdateNoneNoRefGoldenRefAltRef;
295ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[2] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
296ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[3] = kTemporalUpdateNone;
297ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[4] = kTemporalUpdateLastRefAltRef;
298ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[5] = kTemporalUpdateNone;
299ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[6] = kTemporalUpdateGoldenRefAltRef;
300ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPattern[7] = kTemporalUpdateNone;
301ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalPatternLength = 8;
302ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            break;
303ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        }
304ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        default:
305ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        {
306ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            ALOGE("Wrong number of temporal layers %zu", mTemporalLayers);
307ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            return UNKNOWN_ERROR;
308ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        }
309ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    }
310ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
311ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    // Set bitrate values for each layer
312ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    for (size_t i = 0; i < mCodecConfiguration->ts_number_layers; i++) {
313ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        mCodecConfiguration->ts_target_bitrate[i] =
314ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mCodecConfiguration->rc_target_bitrate *
315ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi            mTemporalLayerBitrateRatio[i] / 100;
316ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    }
317ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    if (mKeyFrameInterval > 0) {
3185e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        mCodecConfiguration->kf_max_dist = mKeyFrameInterval;
3195e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten        mCodecConfiguration->kf_min_dist = mKeyFrameInterval;
320ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        mCodecConfiguration->kf_mode = VPX_KF_AUTO;
321ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    }
322ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    if (mMinQuantizer > 0) {
323ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        mCodecConfiguration->rc_min_quantizer = mMinQuantizer;
324ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    }
325c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten    if (mMaxQuantizer > 0) {
326ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        mCodecConfiguration->rc_max_quantizer = mMaxQuantizer;
327ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    }
328ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
329ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    codec_return = vpx_codec_enc_init(mCodecContext,
330ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi                                      mCodecInterface,
331ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi                                      mCodecConfiguration,
332ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi                                      0);  // flags
333ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
334ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    if (codec_return != VPX_CODEC_OK) {
335ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        ALOGE("Error initializing vpx encoder");
336ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        return UNKNOWN_ERROR;
337ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    }
338ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi
339ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    codec_return = vpx_codec_control(mCodecContext,
340ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi                                     VP8E_SET_TOKEN_PARTITIONS,
341ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi                                     mDCTPartitions);
342ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    if (codec_return != VPX_CODEC_OK) {
343ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi        ALOGE("Error setting dct partitions for vpx encoder.");
344c2303eb5497c488db786dcb2b8514db229452536Glenn Kasten        return UNKNOWN_ERROR;
345ece0014725c0f3b8ff6c369aeabd27a71f03510bJean-Michel Trivi    }
346
347    // Extra CBR settings
348    if (mBitrateControlMode == VPX_CBR) {
349        codec_return = vpx_codec_control(mCodecContext,
350                                         VP8E_SET_STATIC_THRESHOLD,
351                                         1);
352        if (codec_return == VPX_CODEC_OK) {
353            uint32_t rc_max_intra_target =
354                mCodecConfiguration->rc_buf_optimal_sz * (mFramerate >> 17) / 10;
355            // Don't go below 3 times per frame bandwidth.
356            if (rc_max_intra_target < 300) {
357                rc_max_intra_target = 300;
358            }
359            codec_return = vpx_codec_control(mCodecContext,
360                                             VP8E_SET_MAX_INTRA_BITRATE_PCT,
361                                             rc_max_intra_target);
362        }
363        if (codec_return == VPX_CODEC_OK) {
364            codec_return = vpx_codec_control(mCodecContext,
365                                             VP8E_SET_CPUUSED,
366                                             -8);
367        }
368        if (codec_return != VPX_CODEC_OK) {
369            ALOGE("Error setting cbr parameters for vpx encoder.");
370            return UNKNOWN_ERROR;
371        }
372    }
373
374    if (mColorFormat != OMX_COLOR_FormatYUV420Planar || mInputDataIsMeta) {
375        free(mConversionBuffer);
376        mConversionBuffer = NULL;
377        if (((uint64_t)mWidth * mHeight) > ((uint64_t)INT32_MAX / 3)) {
378            ALOGE("b/25812794, Buffer size is too big.");
379            return UNKNOWN_ERROR;
380        }
381        mConversionBuffer = (uint8_t *)malloc(mWidth * mHeight * 3 / 2);
382        if (mConversionBuffer == NULL) {
383            ALOGE("Allocating conversion buffer failed.");
384            return UNKNOWN_ERROR;
385        }
386    }
387    return OK;
388}
389
390
391status_t SoftVPXEncoder::releaseEncoder() {
392    if (mCodecContext != NULL) {
393        vpx_codec_destroy(mCodecContext);
394        delete mCodecContext;
395        mCodecContext = NULL;
396    }
397
398    if (mCodecConfiguration != NULL) {
399        delete mCodecConfiguration;
400        mCodecConfiguration = NULL;
401    }
402
403    if (mConversionBuffer != NULL) {
404        free(mConversionBuffer);
405        mConversionBuffer = NULL;
406    }
407
408    // this one is not allocated by us
409    mCodecInterface = NULL;
410
411    return OK;
412}
413
414
415OMX_ERRORTYPE SoftVPXEncoder::internalGetParameter(OMX_INDEXTYPE index,
416                                                   OMX_PTR param) {
417    // can include extension index OMX_INDEXEXTTYPE
418    const int32_t indexFull = index;
419
420    switch (indexFull) {
421        case OMX_IndexParamVideoPortFormat: {
422            OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
423                (OMX_VIDEO_PARAM_PORTFORMATTYPE *)param;
424
425            if (formatParams->nPortIndex == kInputPortIndex) {
426                if (formatParams->nIndex >= kNumberOfSupportedColorFormats) {
427                    return OMX_ErrorNoMore;
428                }
429
430                // Color formats, in order of preference
431                if (formatParams->nIndex == 0) {
432                    formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
433                } else if (formatParams->nIndex == 1) {
434                    formatParams->eColorFormat =
435                        OMX_COLOR_FormatYUV420SemiPlanar;
436                } else {
437                    formatParams->eColorFormat = OMX_COLOR_FormatAndroidOpaque;
438                }
439
440                formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
441                formatParams->xFramerate = mFramerate;
442                return OMX_ErrorNone;
443            } else if (formatParams->nPortIndex == kOutputPortIndex) {
444                formatParams->eCompressionFormat = OMX_VIDEO_CodingVP8;
445                formatParams->eColorFormat = OMX_COLOR_FormatUnused;
446                formatParams->xFramerate = 0;
447                return OMX_ErrorNone;
448            } else {
449                return OMX_ErrorBadPortIndex;
450            }
451        }
452
453        case OMX_IndexParamVideoBitrate: {
454            OMX_VIDEO_PARAM_BITRATETYPE *bitrate =
455                (OMX_VIDEO_PARAM_BITRATETYPE *)param;
456
457            if (!isValidOMXParam(bitrate)) {
458                return OMX_ErrorBadParameter;
459            }
460
461            if (bitrate->nPortIndex != kOutputPortIndex) {
462                return OMX_ErrorUnsupportedIndex;
463            }
464
465            bitrate->nTargetBitrate = mBitrate;
466
467            if (mBitrateControlMode == VPX_VBR) {
468                bitrate->eControlRate = OMX_Video_ControlRateVariable;
469            } else if (mBitrateControlMode == VPX_CBR) {
470                bitrate->eControlRate = OMX_Video_ControlRateConstant;
471            } else {
472                return OMX_ErrorUnsupportedSetting;
473            }
474            return OMX_ErrorNone;
475        }
476
477        // VP8 specific parameters that use extension headers
478        case OMX_IndexParamVideoVp8: {
479            OMX_VIDEO_PARAM_VP8TYPE *vp8Params =
480                (OMX_VIDEO_PARAM_VP8TYPE *)param;
481
482            if (!isValidOMXParam(vp8Params)) {
483                return OMX_ErrorBadParameter;
484            }
485
486            if (vp8Params->nPortIndex != kOutputPortIndex) {
487                return OMX_ErrorUnsupportedIndex;
488            }
489
490            vp8Params->eProfile = OMX_VIDEO_VP8ProfileMain;
491            vp8Params->eLevel = mLevel;
492            vp8Params->nDCTPartitions = mDCTPartitions;
493            vp8Params->bErrorResilientMode = mErrorResilience;
494            return OMX_ErrorNone;
495        }
496
497        case OMX_IndexParamVideoAndroidVp8Encoder: {
498            OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *vp8AndroidParams =
499                (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param;
500
501                if (vp8AndroidParams->nPortIndex != kOutputPortIndex) {
502                    return OMX_ErrorUnsupportedIndex;
503                }
504
505                vp8AndroidParams->nKeyFrameInterval = mKeyFrameInterval;
506                vp8AndroidParams->eTemporalPattern = mTemporalPatternType;
507                vp8AndroidParams->nTemporalLayerCount = mTemporalLayers;
508                vp8AndroidParams->nMinQuantizer = mMinQuantizer;
509                vp8AndroidParams->nMaxQuantizer = mMaxQuantizer;
510                memcpy(vp8AndroidParams->nTemporalLayerBitrateRatio,
511                       mTemporalLayerBitrateRatio, sizeof(mTemporalLayerBitrateRatio));
512                return OMX_ErrorNone;
513        }
514
515        case OMX_IndexParamVideoProfileLevelQuerySupported: {
516            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileAndLevel =
517                (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param;
518
519            if (!isValidOMXParam(profileAndLevel)) {
520                return OMX_ErrorBadParameter;
521            }
522
523            if (profileAndLevel->nPortIndex != kOutputPortIndex) {
524                return OMX_ErrorUnsupportedIndex;
525            }
526
527            switch (profileAndLevel->nProfileIndex) {
528                case 0:
529                    profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version0;
530                    break;
531
532                case 1:
533                    profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version1;
534                    break;
535
536                case 2:
537                    profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version2;
538                    break;
539
540                case 3:
541                    profileAndLevel->eLevel = OMX_VIDEO_VP8Level_Version3;
542                    break;
543
544                default:
545                    return OMX_ErrorNoMore;
546            }
547
548            profileAndLevel->eProfile = OMX_VIDEO_VP8ProfileMain;
549            return OMX_ErrorNone;
550        }
551
552        case OMX_IndexParamVideoProfileLevelCurrent: {
553            OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileAndLevel =
554                (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param;
555
556            if (!isValidOMXParam(profileAndLevel)) {
557                return OMX_ErrorBadParameter;
558            }
559
560            if (profileAndLevel->nPortIndex != kOutputPortIndex) {
561                return OMX_ErrorUnsupportedIndex;
562            }
563
564            profileAndLevel->eLevel = mLevel;
565            profileAndLevel->eProfile = OMX_VIDEO_VP8ProfileMain;
566            return OMX_ErrorNone;
567        }
568
569        default:
570            return SimpleSoftOMXComponent::internalGetParameter(index, param);
571    }
572}
573
574
575OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index,
576                                                   const OMX_PTR param) {
577    // can include extension index OMX_INDEXEXTTYPE
578    const int32_t indexFull = index;
579
580    switch (indexFull) {
581        case OMX_IndexParamStandardComponentRole: {
582            const OMX_PARAM_COMPONENTROLETYPE *role =
583                (const OMX_PARAM_COMPONENTROLETYPE*) param;
584
585            if (!isValidOMXParam(role)) {
586                return OMX_ErrorBadParameter;
587            }
588            return internalSetRoleParams(role);
589        }
590
591        case OMX_IndexParamVideoBitrate: {
592            const OMX_VIDEO_PARAM_BITRATETYPE *bitRate =
593                (const OMX_VIDEO_PARAM_BITRATETYPE*) param;
594
595            if (!isValidOMXParam(bitRate)) {
596                return OMX_ErrorBadParameter;
597            }
598
599            return internalSetBitrateParams(bitRate);
600        }
601
602        case OMX_IndexParamPortDefinition:
603        {
604            const OMX_PARAM_PORTDEFINITIONTYPE *portDefinition =
605                (const OMX_PARAM_PORTDEFINITIONTYPE*) param;
606
607            if (!isValidOMXParam(portDefinition)) {
608                return OMX_ErrorBadParameter;
609            }
610
611            OMX_ERRORTYPE err = internalSetPortParams(portDefinition);
612
613            if (err != OMX_ErrorNone) {
614                return err;
615            }
616
617            return SimpleSoftOMXComponent::internalSetParameter(index, param);
618        }
619
620        case OMX_IndexParamVideoPortFormat: {
621            const OMX_VIDEO_PARAM_PORTFORMATTYPE *portFormatType =
622                (const OMX_VIDEO_PARAM_PORTFORMATTYPE*) param;
623
624            if (!isValidOMXParam(portFormatType)) {
625                return OMX_ErrorBadParameter;
626            }
627            return internalSetFormatParams(portFormatType);
628        }
629
630        case OMX_IndexParamVideoVp8: {
631            const OMX_VIDEO_PARAM_VP8TYPE *vp8Params =
632                (const OMX_VIDEO_PARAM_VP8TYPE*) param;
633
634            if (!isValidOMXParam(vp8Params)) {
635                return OMX_ErrorBadParameter;
636            }
637
638            return internalSetVp8Params(vp8Params);
639        }
640
641        case OMX_IndexParamVideoProfileLevelCurrent: {
642            const OMX_VIDEO_PARAM_PROFILELEVELTYPE *vp8Params =
643                (const OMX_VIDEO_PARAM_PROFILELEVELTYPE*) param;
644
645            if (!isValidOMXParam(vp8Params)) {
646                return OMX_ErrorBadParameter;
647            }
648
649            return internalSetProfileLevel(vp8Params);
650        }
651
652        case OMX_IndexParamVideoAndroidVp8Encoder:
653            return internalSetAndroidVp8Params(
654                (const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)param);
655
656        case kStoreMetaDataExtensionIndex:
657        {
658            // storeMetaDataInBuffers
659            const StoreMetaDataInBuffersParams *storeParam =
660                (const StoreMetaDataInBuffersParams *)param;
661
662            if (!isValidOMXParam(storeParam)) {
663                return OMX_ErrorBadParameter;
664            }
665
666            if (storeParam->nPortIndex != kInputPortIndex) {
667                return OMX_ErrorBadPortIndex;
668            }
669
670            mInputDataIsMeta = (storeParam->bStoreMetaData == OMX_TRUE);
671
672            return OMX_ErrorNone;
673        }
674
675        default:
676            return SimpleSoftOMXComponent::internalSetParameter(index, param);
677    }
678}
679
680OMX_ERRORTYPE SoftVPXEncoder::setConfig(
681        OMX_INDEXTYPE index, const OMX_PTR _params) {
682    switch (index) {
683        case OMX_IndexConfigVideoIntraVOPRefresh:
684        {
685            OMX_CONFIG_INTRAREFRESHVOPTYPE *params =
686                (OMX_CONFIG_INTRAREFRESHVOPTYPE *)_params;
687
688            if (!isValidOMXParam(params)) {
689                return OMX_ErrorBadParameter;
690            }
691
692            if (params->nPortIndex != kOutputPortIndex) {
693                return OMX_ErrorBadPortIndex;
694            }
695
696            mKeyFrameRequested = params->IntraRefreshVOP;
697            return OMX_ErrorNone;
698        }
699
700        case OMX_IndexConfigVideoBitrate:
701        {
702            OMX_VIDEO_CONFIG_BITRATETYPE *params =
703                (OMX_VIDEO_CONFIG_BITRATETYPE *)_params;
704
705            if (!isValidOMXParam(params)) {
706                return OMX_ErrorBadParameter;
707            }
708
709            if (params->nPortIndex != kOutputPortIndex) {
710                return OMX_ErrorBadPortIndex;
711            }
712
713            if (mBitrate != params->nEncodeBitrate) {
714                mBitrate = params->nEncodeBitrate;
715                mBitrateUpdated = true;
716            }
717            return OMX_ErrorNone;
718        }
719
720        default:
721            return SimpleSoftOMXComponent::setConfig(index, _params);
722    }
723}
724
725OMX_ERRORTYPE SoftVPXEncoder::internalSetProfileLevel(
726        const OMX_VIDEO_PARAM_PROFILELEVELTYPE* profileAndLevel) {
727
728    if (!isValidOMXParam(profileAndLevel)) {
729        return OMX_ErrorBadParameter;
730    }
731
732    if (profileAndLevel->nPortIndex != kOutputPortIndex) {
733        return OMX_ErrorUnsupportedIndex;
734    }
735
736    if (profileAndLevel->eProfile != OMX_VIDEO_VP8ProfileMain) {
737        return OMX_ErrorBadParameter;
738    }
739
740    if (profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version0 ||
741        profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version1 ||
742        profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version2 ||
743        profileAndLevel->eLevel == OMX_VIDEO_VP8Level_Version3) {
744        mLevel = (OMX_VIDEO_VP8LEVELTYPE)profileAndLevel->eLevel;
745    } else {
746        return OMX_ErrorBadParameter;
747    }
748
749    return OMX_ErrorNone;
750}
751
752
753OMX_ERRORTYPE SoftVPXEncoder::internalSetVp8Params(
754        const OMX_VIDEO_PARAM_VP8TYPE* vp8Params) {
755    if (vp8Params->nPortIndex != kOutputPortIndex) {
756        return OMX_ErrorUnsupportedIndex;
757    }
758
759    if (vp8Params->eProfile != OMX_VIDEO_VP8ProfileMain) {
760        return OMX_ErrorBadParameter;
761    }
762
763    if (vp8Params->eLevel == OMX_VIDEO_VP8Level_Version0 ||
764        vp8Params->eLevel == OMX_VIDEO_VP8Level_Version1 ||
765        vp8Params->eLevel == OMX_VIDEO_VP8Level_Version2 ||
766        vp8Params->eLevel == OMX_VIDEO_VP8Level_Version3) {
767        mLevel = vp8Params->eLevel;
768    } else {
769        return OMX_ErrorBadParameter;
770    }
771
772    if (vp8Params->nDCTPartitions <= kMaxDCTPartitions) {
773        mDCTPartitions = vp8Params->nDCTPartitions;
774    } else {
775        return OMX_ErrorBadParameter;
776    }
777
778    mErrorResilience = vp8Params->bErrorResilientMode;
779    return OMX_ErrorNone;
780}
781
782OMX_ERRORTYPE SoftVPXEncoder::internalSetAndroidVp8Params(
783        const OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE* vp8AndroidParams) {
784
785    if (!isValidOMXParam(vp8AndroidParams)) {
786        return OMX_ErrorBadParameter;
787    }
788
789    if (vp8AndroidParams->nPortIndex != kOutputPortIndex) {
790        return OMX_ErrorUnsupportedIndex;
791    }
792    if (vp8AndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternNone &&
793        vp8AndroidParams->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
794        return OMX_ErrorBadParameter;
795    }
796    if (vp8AndroidParams->nTemporalLayerCount > OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS) {
797        return OMX_ErrorBadParameter;
798    }
799    if (vp8AndroidParams->nMinQuantizer > vp8AndroidParams->nMaxQuantizer) {
800        return OMX_ErrorBadParameter;
801    }
802
803    mTemporalPatternType = vp8AndroidParams->eTemporalPattern;
804    if (vp8AndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternWebRTC) {
805        mTemporalLayers = vp8AndroidParams->nTemporalLayerCount;
806    } else if (vp8AndroidParams->eTemporalPattern == OMX_VIDEO_VPXTemporalLayerPatternNone) {
807        mTemporalLayers = 0;
808    }
809    // Check the bitrate distribution between layers is in increasing order
810    if (mTemporalLayers > 1) {
811        for (size_t i = 0; i < mTemporalLayers - 1; i++) {
812            if (vp8AndroidParams->nTemporalLayerBitrateRatio[i + 1] <=
813                    vp8AndroidParams->nTemporalLayerBitrateRatio[i]) {
814                ALOGE("Wrong bitrate ratio - should be in increasing order.");
815                return OMX_ErrorBadParameter;
816            }
817        }
818    }
819    mKeyFrameInterval = vp8AndroidParams->nKeyFrameInterval;
820    mMinQuantizer = vp8AndroidParams->nMinQuantizer;
821    mMaxQuantizer = vp8AndroidParams->nMaxQuantizer;
822    memcpy(mTemporalLayerBitrateRatio, vp8AndroidParams->nTemporalLayerBitrateRatio,
823            sizeof(mTemporalLayerBitrateRatio));
824    ALOGD("VP8: internalSetAndroidVp8Params. BRMode: %u. TS: %zu. KF: %u."
825          " QP: %u - %u BR0: %u. BR1: %u. BR2: %u",
826          (uint32_t)mBitrateControlMode, mTemporalLayers, mKeyFrameInterval,
827          mMinQuantizer, mMaxQuantizer, mTemporalLayerBitrateRatio[0],
828          mTemporalLayerBitrateRatio[1], mTemporalLayerBitrateRatio[2]);
829    return OMX_ErrorNone;
830}
831
832OMX_ERRORTYPE SoftVPXEncoder::internalSetFormatParams(
833        const OMX_VIDEO_PARAM_PORTFORMATTYPE* format) {
834    if (format->nPortIndex == kInputPortIndex) {
835        if (format->eColorFormat == OMX_COLOR_FormatYUV420Planar ||
836            format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
837            format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
838            mColorFormat = format->eColorFormat;
839
840            OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
841            def->format.video.eColorFormat = mColorFormat;
842
843            return OMX_ErrorNone;
844        } else {
845            ALOGE("Unsupported color format %i", format->eColorFormat);
846            return OMX_ErrorUnsupportedSetting;
847        }
848    } else if (format->nPortIndex == kOutputPortIndex) {
849        if (format->eCompressionFormat == OMX_VIDEO_CodingVP8) {
850            return OMX_ErrorNone;
851        } else {
852            return OMX_ErrorUnsupportedSetting;
853        }
854    } else {
855        return OMX_ErrorBadPortIndex;
856    }
857}
858
859
860OMX_ERRORTYPE SoftVPXEncoder::internalSetRoleParams(
861        const OMX_PARAM_COMPONENTROLETYPE* role) {
862    const char* roleText = (const char*)role->cRole;
863    const size_t roleTextMaxSize = OMX_MAX_STRINGNAME_SIZE - 1;
864
865    if (strncmp(roleText, "video_encoder.vp8", roleTextMaxSize)) {
866        ALOGE("Unsupported component role");
867        return OMX_ErrorBadParameter;
868    }
869
870    return OMX_ErrorNone;
871}
872
873
874OMX_ERRORTYPE SoftVPXEncoder::internalSetPortParams(
875        const OMX_PARAM_PORTDEFINITIONTYPE* port) {
876    if (port->nPortIndex == kInputPortIndex) {
877        mWidth = port->format.video.nFrameWidth;
878        mHeight = port->format.video.nFrameHeight;
879
880        // xFramerate comes in Q16 format, in frames per second unit
881        mFramerate = port->format.video.xFramerate;
882
883        if (port->format.video.eColorFormat == OMX_COLOR_FormatYUV420Planar ||
884            port->format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
885            port->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
886            mColorFormat = port->format.video.eColorFormat;
887        } else {
888            return OMX_ErrorUnsupportedSetting;
889        }
890
891        OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
892        def->format.video.nFrameWidth = mWidth;
893        def->format.video.nFrameHeight = mHeight;
894        def->format.video.xFramerate = mFramerate;
895        def->format.video.eColorFormat = mColorFormat;
896        def = &editPortInfo(kOutputPortIndex)->mDef;
897        def->format.video.nFrameWidth = mWidth;
898        def->format.video.nFrameHeight = mHeight;
899
900        return OMX_ErrorNone;
901    } else if (port->nPortIndex == kOutputPortIndex) {
902        mBitrate = port->format.video.nBitrate;
903        mWidth = port->format.video.nFrameWidth;
904        mHeight = port->format.video.nFrameHeight;
905
906        OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kOutputPortIndex)->mDef;
907        def->format.video.nFrameWidth = mWidth;
908        def->format.video.nFrameHeight = mHeight;
909        def->format.video.nBitrate = mBitrate;
910        return OMX_ErrorNone;
911    } else {
912        return OMX_ErrorBadPortIndex;
913    }
914}
915
916
917OMX_ERRORTYPE SoftVPXEncoder::internalSetBitrateParams(
918        const OMX_VIDEO_PARAM_BITRATETYPE* bitrate) {
919    if (bitrate->nPortIndex != kOutputPortIndex) {
920        return OMX_ErrorUnsupportedIndex;
921    }
922
923    mBitrate = bitrate->nTargetBitrate;
924
925    if (bitrate->eControlRate == OMX_Video_ControlRateVariable) {
926        mBitrateControlMode = VPX_VBR;
927    } else if (bitrate->eControlRate == OMX_Video_ControlRateConstant) {
928        mBitrateControlMode = VPX_CBR;
929    } else {
930        return OMX_ErrorUnsupportedSetting;
931    }
932
933    return OMX_ErrorNone;
934}
935
936vpx_enc_frame_flags_t SoftVPXEncoder::getEncodeFlags() {
937    vpx_enc_frame_flags_t flags = 0;
938    int patternIdx = mTemporalPatternIdx % mTemporalPatternLength;
939    mTemporalPatternIdx++;
940    switch (mTemporalPattern[patternIdx]) {
941        case kTemporalUpdateLast:
942            flags |= VP8_EFLAG_NO_UPD_GF;
943            flags |= VP8_EFLAG_NO_UPD_ARF;
944            flags |= VP8_EFLAG_NO_REF_GF;
945            flags |= VP8_EFLAG_NO_REF_ARF;
946            break;
947        case kTemporalUpdateGoldenWithoutDependency:
948            flags |= VP8_EFLAG_NO_REF_GF;
949            // Deliberately no break here.
950        case kTemporalUpdateGolden:
951            flags |= VP8_EFLAG_NO_REF_ARF;
952            flags |= VP8_EFLAG_NO_UPD_ARF;
953            flags |= VP8_EFLAG_NO_UPD_LAST;
954            break;
955        case kTemporalUpdateAltrefWithoutDependency:
956            flags |= VP8_EFLAG_NO_REF_ARF;
957            flags |= VP8_EFLAG_NO_REF_GF;
958            // Deliberately no break here.
959        case kTemporalUpdateAltref:
960            flags |= VP8_EFLAG_NO_UPD_GF;
961            flags |= VP8_EFLAG_NO_UPD_LAST;
962            break;
963        case kTemporalUpdateNoneNoRefAltref:
964            flags |= VP8_EFLAG_NO_REF_ARF;
965            // Deliberately no break here.
966        case kTemporalUpdateNone:
967            flags |= VP8_EFLAG_NO_UPD_GF;
968            flags |= VP8_EFLAG_NO_UPD_ARF;
969            flags |= VP8_EFLAG_NO_UPD_LAST;
970            flags |= VP8_EFLAG_NO_UPD_ENTROPY;
971            break;
972        case kTemporalUpdateNoneNoRefGoldenRefAltRef:
973            flags |= VP8_EFLAG_NO_REF_GF;
974            flags |= VP8_EFLAG_NO_UPD_GF;
975            flags |= VP8_EFLAG_NO_UPD_ARF;
976            flags |= VP8_EFLAG_NO_UPD_LAST;
977            flags |= VP8_EFLAG_NO_UPD_ENTROPY;
978            break;
979        case kTemporalUpdateGoldenWithoutDependencyRefAltRef:
980            flags |= VP8_EFLAG_NO_REF_GF;
981            flags |= VP8_EFLAG_NO_UPD_ARF;
982            flags |= VP8_EFLAG_NO_UPD_LAST;
983            break;
984        case kTemporalUpdateLastRefAltRef:
985            flags |= VP8_EFLAG_NO_UPD_GF;
986            flags |= VP8_EFLAG_NO_UPD_ARF;
987            flags |= VP8_EFLAG_NO_REF_GF;
988            break;
989        case kTemporalUpdateGoldenRefAltRef:
990            flags |= VP8_EFLAG_NO_UPD_ARF;
991            flags |= VP8_EFLAG_NO_UPD_LAST;
992            break;
993        case kTemporalUpdateLastAndGoldenRefAltRef:
994            flags |= VP8_EFLAG_NO_UPD_ARF;
995            flags |= VP8_EFLAG_NO_REF_GF;
996            break;
997        case kTemporalUpdateLastRefAll:
998            flags |= VP8_EFLAG_NO_UPD_ARF;
999            flags |= VP8_EFLAG_NO_UPD_GF;
1000            break;
1001    }
1002    return flags;
1003}
1004
1005void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) {
1006    // Initialize encoder if not already
1007    if (mCodecContext == NULL) {
1008        if (OK != initEncoder()) {
1009            ALOGE("Failed to initialize encoder");
1010            notify(OMX_EventError,
1011                   OMX_ErrorUndefined,
1012                   0,  // Extra notification data
1013                   NULL);  // Notification data pointer
1014            return;
1015        }
1016    }
1017
1018    vpx_codec_err_t codec_return;
1019    List<BufferInfo *> &inputBufferInfoQueue = getPortQueue(kInputPortIndex);
1020    List<BufferInfo *> &outputBufferInfoQueue = getPortQueue(kOutputPortIndex);
1021
1022    while (!inputBufferInfoQueue.empty() && !outputBufferInfoQueue.empty()) {
1023        BufferInfo *inputBufferInfo = *inputBufferInfoQueue.begin();
1024        OMX_BUFFERHEADERTYPE *inputBufferHeader = inputBufferInfo->mHeader;
1025
1026        BufferInfo *outputBufferInfo = *outputBufferInfoQueue.begin();
1027        OMX_BUFFERHEADERTYPE *outputBufferHeader = outputBufferInfo->mHeader;
1028
1029        if (inputBufferHeader->nFlags & OMX_BUFFERFLAG_EOS) {
1030            inputBufferInfoQueue.erase(inputBufferInfoQueue.begin());
1031            inputBufferInfo->mOwnedByUs = false;
1032            notifyEmptyBufferDone(inputBufferHeader);
1033
1034            outputBufferHeader->nFilledLen = 0;
1035            outputBufferHeader->nFlags = OMX_BUFFERFLAG_EOS;
1036
1037            outputBufferInfoQueue.erase(outputBufferInfoQueue.begin());
1038            outputBufferInfo->mOwnedByUs = false;
1039            notifyFillBufferDone(outputBufferHeader);
1040            return;
1041        }
1042
1043        const uint8_t *source =
1044            inputBufferHeader->pBuffer + inputBufferHeader->nOffset;
1045
1046        size_t frameSize = mWidth * mHeight * 3 / 2;
1047        if (mInputDataIsMeta) {
1048            source = extractGraphicBuffer(
1049                    mConversionBuffer, frameSize,
1050                    source, inputBufferHeader->nFilledLen,
1051                    mWidth, mHeight);
1052            if (source == NULL) {
1053                ALOGE("Unable to extract gralloc buffer in metadata mode");
1054                notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
1055                return;
1056            }
1057        } else {
1058            if (inputBufferHeader->nFilledLen < frameSize) {
1059                android_errorWriteLog(0x534e4554, "27569635");
1060                notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
1061                return;
1062            } else if (inputBufferHeader->nFilledLen > frameSize) {
1063                ALOGW("Input buffer contains too many pixels");
1064            }
1065
1066            if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
1067                ConvertYUV420SemiPlanarToYUV420Planar(
1068                        source, mConversionBuffer, mWidth, mHeight);
1069
1070                source = mConversionBuffer;
1071            }
1072        }
1073        vpx_image_t raw_frame;
1074        vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, mWidth, mHeight,
1075                     kInputBufferAlignment, (uint8_t *)source);
1076
1077        vpx_enc_frame_flags_t flags = 0;
1078        if (mTemporalPatternLength > 0) {
1079            flags = getEncodeFlags();
1080        }
1081        if (mKeyFrameRequested) {
1082            flags |= VPX_EFLAG_FORCE_KF;
1083            mKeyFrameRequested = false;
1084        }
1085
1086        if (mBitrateUpdated) {
1087            mCodecConfiguration->rc_target_bitrate = mBitrate/1000;
1088            vpx_codec_err_t res = vpx_codec_enc_config_set(mCodecContext,
1089                                                           mCodecConfiguration);
1090            if (res != VPX_CODEC_OK) {
1091                ALOGE("vp8 encoder failed to update bitrate: %s",
1092                      vpx_codec_err_to_string(res));
1093                notify(OMX_EventError,
1094                       OMX_ErrorUndefined,
1095                       0, // Extra notification data
1096                       NULL); // Notification data pointer
1097            }
1098            mBitrateUpdated = false;
1099        }
1100
1101        uint32_t frameDuration;
1102        if (inputBufferHeader->nTimeStamp > mLastTimestamp) {
1103            frameDuration = (uint32_t)(inputBufferHeader->nTimeStamp - mLastTimestamp);
1104        } else {
1105            frameDuration = (uint32_t)(((uint64_t)1000000 << 16) / mFramerate);
1106        }
1107        mLastTimestamp = inputBufferHeader->nTimeStamp;
1108        codec_return = vpx_codec_encode(
1109                mCodecContext,
1110                &raw_frame,
1111                inputBufferHeader->nTimeStamp,  // in timebase units
1112                frameDuration,  // frame duration in timebase units
1113                flags,  // frame flags
1114                VPX_DL_REALTIME);  // encoding deadline
1115        if (codec_return != VPX_CODEC_OK) {
1116            ALOGE("vpx encoder failed to encode frame");
1117            notify(OMX_EventError,
1118                   OMX_ErrorUndefined,
1119                   0,  // Extra notification data
1120                   NULL);  // Notification data pointer
1121            return;
1122        }
1123
1124        vpx_codec_iter_t encoded_packet_iterator = NULL;
1125        const vpx_codec_cx_pkt_t* encoded_packet;
1126
1127        while ((encoded_packet = vpx_codec_get_cx_data(
1128                        mCodecContext, &encoded_packet_iterator))) {
1129            if (encoded_packet->kind == VPX_CODEC_CX_FRAME_PKT) {
1130                outputBufferHeader->nTimeStamp = encoded_packet->data.frame.pts;
1131                outputBufferHeader->nFlags = 0;
1132                if (encoded_packet->data.frame.flags & VPX_FRAME_IS_KEY)
1133                    outputBufferHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
1134                outputBufferHeader->nOffset = 0;
1135                outputBufferHeader->nFilledLen = encoded_packet->data.frame.sz;
1136                if (outputBufferHeader->nFilledLen > outputBufferHeader->nAllocLen) {
1137                    android_errorWriteLog(0x534e4554, "27569635");
1138                    notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
1139                    return;
1140                }
1141                memcpy(outputBufferHeader->pBuffer,
1142                       encoded_packet->data.frame.buf,
1143                       encoded_packet->data.frame.sz);
1144                outputBufferInfo->mOwnedByUs = false;
1145                outputBufferInfoQueue.erase(outputBufferInfoQueue.begin());
1146                notifyFillBufferDone(outputBufferHeader);
1147            }
1148        }
1149
1150        inputBufferInfo->mOwnedByUs = false;
1151        inputBufferInfoQueue.erase(inputBufferInfoQueue.begin());
1152        notifyEmptyBufferDone(inputBufferHeader);
1153    }
1154}
1155
1156}  // namespace android
1157
1158
1159android::SoftOMXComponent *createSoftOMXComponent(
1160        const char *name, const OMX_CALLBACKTYPE *callbacks,
1161        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
1162    return new android::SoftVPXEncoder(name, callbacks, appData, component);
1163}
1164