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