1bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber/* 2bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Copyright (C) 2011 The Android Open Source Project 3bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * 4bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * you may not use this file except in compliance with the License. 6bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * You may obtain a copy of the License at 7bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * 8bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * 10bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Unless required by applicable law or agreed to in writing, software 11bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * See the License for the specific language governing permissions and 14bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * limitations under the License. 15bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber */ 16bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 17bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber//#define LOG_NDEBUG 0 18bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#define LOG_TAG "SoftVPX" 19bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <utils/Log.h> 209486e0a16e9ad4d4f6bd5047a3cbb1b3f2008d65Hangyu Kuang#include <utils/misc.h> 219486e0a16e9ad4d4f6bd5047a3cbb1b3f2008d65Hangyu Kuang#include "OMX_VideoExt.h" 22bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 23bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include "SoftVPX.h" 24bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 25bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <media/stagefright/foundation/ADebug.h> 26bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <media/stagefright/MediaDefs.h> 27bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 28bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 29bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubernamespace android { 30bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 319486e0a16e9ad4d4f6bd5047a3cbb1b3f2008d65Hangyu Kuang// Only need to declare the highest supported profile and level here. 329486e0a16e9ad4d4f6bd5047a3cbb1b3f2008d65Hangyu Kuangstatic const CodecProfileLevel kVP9ProfileLevels[] = { 332d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang { OMX_VIDEO_VP9Profile0, OMX_VIDEO_VP9Level5 }, 342d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang { OMX_VIDEO_VP9Profile2, OMX_VIDEO_VP9Level5 }, 352d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang { OMX_VIDEO_VP9Profile2HDR, OMX_VIDEO_VP9Level5 }, 369486e0a16e9ad4d4f6bd5047a3cbb1b3f2008d65Hangyu Kuang}; 379486e0a16e9ad4d4f6bd5047a3cbb1b3f2008d65Hangyu Kuang 38bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberSoftVPX::SoftVPX( 39bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const char *name, 4094705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang const char *componentRole, 4194705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang OMX_VIDEO_CODINGTYPE codingType, 42bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const OMX_CALLBACKTYPE *callbacks, 43bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_PTR appData, 44bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_COMPONENTTYPE **component) 457f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar : SoftVideoDecoderOMXComponent( 4694705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang name, componentRole, codingType, 479486e0a16e9ad4d4f6bd5047a3cbb1b3f2008d65Hangyu Kuang codingType == OMX_VIDEO_CodingVP8 ? NULL : kVP9ProfileLevels, 489486e0a16e9ad4d4f6bd5047a3cbb1b3f2008d65Hangyu Kuang codingType == OMX_VIDEO_CodingVP8 ? 0 : NELEM(kVP9ProfileLevels), 497f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar 320 /* width */, 240 /* height */, callbacks, appData, component), 5094705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang mMode(codingType == OMX_VIDEO_CodingVP8 ? MODE_VP8 : MODE_VP9), 51d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus(INPUT_DATA_AVAILABLE), 5250f939d655a5156157564cb91434f1cce424b2ddhkuang mCtx(NULL), 53d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mFrameParallelMode(false), 54d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mTimeStampIdx(0), 5550f939d655a5156157564cb91434f1cce424b2ddhkuang mImg(NULL) { 56a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar // arbitrary from avc/hevc as vpx does not specify a min compression ratio 57a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar const size_t kMinCompressionRatio = mMode == MODE_VP8 ? 2 : 4; 58a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar const char *mime = mMode == MODE_VP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9; 59a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2; 60a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar initPorts( 61a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar kNumBuffers, kMaxOutputBufferSize / kMinCompressionRatio /* inputBufferSize */, 62a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar kNumBuffers, mime, kMinCompressionRatio); 63bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber CHECK_EQ(initDecoder(), (status_t)OK); 64bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 65bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 66bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberSoftVPX::~SoftVPX() { 67d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang destroyDecoder(); 68bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 69bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 70f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dongstatic int GetCPUCoreCount() { 71f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong int cpuCoreCount = 1; 72f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong#if defined(_SC_NPROCESSORS_ONLN) 73f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN); 74f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong#else 75f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong // _SC_NPROC_ONLN must be defined... 76f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong cpuCoreCount = sysconf(_SC_NPROC_ONLN); 77f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong#endif 78f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong CHECK(cpuCoreCount >= 1); 793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Number of CPU cores: %d", cpuCoreCount); 80f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong return cpuCoreCount; 81f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong} 82f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong 832d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhangbool SoftVPX::supportDescribeHdrStaticInfo() { 842d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang return true; 852d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang} 862d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang 87bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberstatus_t SoftVPX::initDecoder() { 88bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber mCtx = new vpx_codec_ctx_t; 89bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber vpx_codec_err_t vpx_err; 90f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong vpx_codec_dec_cfg_t cfg; 91d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang vpx_codec_flags_t flags; 92f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t)); 93d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang memset(&flags, 0, sizeof(vpx_codec_flags_t)); 94f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong cfg.threads = GetCPUCoreCount(); 95d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 96d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (mFrameParallelMode) { 97d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang flags |= VPX_CODEC_USE_FRAME_THREADING; 98d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 99d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 100bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber if ((vpx_err = vpx_codec_dec_init( 10194705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang (vpx_codec_ctx_t *)mCtx, 10294705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang mMode == MODE_VP8 ? &vpx_codec_vp8_dx_algo : &vpx_codec_vp9_dx_algo, 103d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang &cfg, flags))) { 10429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("on2 decoder failed to initialize. (%d)", vpx_err); 105bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return UNKNOWN_ERROR; 106bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 107bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 108bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return OK; 109bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 110bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 111d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuangstatus_t SoftVPX::destroyDecoder() { 112d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang vpx_codec_destroy((vpx_codec_ctx_t *)mCtx); 113d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang delete (vpx_codec_ctx_t *)mCtx; 114d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mCtx = NULL; 115d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return OK; 116d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang} 117d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 118d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuangbool SoftVPX::outputBuffers(bool flushDecoder, bool display, bool eos, bool *portWillReset) { 119d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang List<BufferInfo *> &outQueue = getPortQueue(1); 120d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang BufferInfo *outInfo = NULL; 121d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang OMX_BUFFERHEADERTYPE *outHeader = NULL; 122d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang vpx_codec_iter_t iter = NULL; 123d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 124d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (flushDecoder && mFrameParallelMode) { 125d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang // Flush decoder by passing NULL data ptr and 0 size. 126d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang // Ideally, this should never fail. 127d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (vpx_codec_decode((vpx_codec_ctx_t *)mCtx, NULL, 0, NULL, 0)) { 128d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGE("Failed to flush on2 decoder."); 129d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return false; 130d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 131d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 132d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 133d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!display) { 134d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!flushDecoder) { 135d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGE("Invalid operation."); 136d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return false; 137d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 138d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang // Drop all the decoded frames in decoder. 139d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang while ((mImg = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter))) { 140d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 141d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return true; 142d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 143d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 144d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang while (!outQueue.empty()) { 145d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (mImg == NULL) { 146d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mImg = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter); 147d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (mImg == NULL) { 148d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang break; 149d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 150d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 151d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang uint32_t width = mImg->d_w; 152d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang uint32_t height = mImg->d_h; 153d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo = *outQueue.begin(); 154d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader = outInfo->mHeader; 1552d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang CHECK(mImg->fmt == VPX_IMG_FMT_I420 || mImg->fmt == VPX_IMG_FMT_I42016); 1562d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang OMX_COLOR_FORMATTYPE outputColorFormat = OMX_COLOR_FormatYUV420Planar; 1572d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang int32_t bpp = 1; 1582d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang if (mImg->fmt == VPX_IMG_FMT_I42016) { 1592d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang outputColorFormat = OMX_COLOR_FormatYUV420Planar16; 1602d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang bpp = 2; 1612d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang } 1622d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang handlePortSettingsChange(portWillReset, width, height, outputColorFormat); 163d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (*portWillReset) { 164d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return true; 165d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 166d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 167d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nOffset = 0; 168d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nFlags = 0; 1692d2a2967ce29281816b9ddb9434b3c0084e4ce52Chong Zhang outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * bpp * 3) / 2; 170d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nTimeStamp = *(OMX_TICKS *)mImg->user_priv; 1717cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih if (outputBufferSafe(outHeader)) { 172ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen uint8_t *dst = outHeader->pBuffer; 173ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen const uint8_t *srcY = (const uint8_t *)mImg->planes[VPX_PLANE_Y]; 174ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen const uint8_t *srcU = (const uint8_t *)mImg->planes[VPX_PLANE_U]; 175ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen const uint8_t *srcV = (const uint8_t *)mImg->planes[VPX_PLANE_V]; 176ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen size_t srcYStride = mImg->stride[VPX_PLANE_Y]; 177ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen size_t srcUStride = mImg->stride[VPX_PLANE_U]; 178ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen size_t srcVStride = mImg->stride[VPX_PLANE_V]; 179ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride); 180ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen } else { 181ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen outHeader->nFilledLen = 0; 182ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen } 183d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 184d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mImg = NULL; 185d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo->mOwnedByUs = false; 186d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outQueue.erase(outQueue.begin()); 187d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo = NULL; 188d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notifyFillBufferDone(outHeader); 189d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader = NULL; 190d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 191d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 192d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!eos) { 193d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return true; 194d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 195d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 196d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outQueue.empty()) { 197d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo = *outQueue.begin(); 198d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outQueue.erase(outQueue.begin()); 199d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader = outInfo->mHeader; 200d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nTimeStamp = 0; 201d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nFilledLen = 0; 202d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nFlags = OMX_BUFFERFLAG_EOS; 203d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo->mOwnedByUs = false; 204d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notifyFillBufferDone(outHeader); 205d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus = OUTPUT_FRAMES_FLUSHED; 206d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 207d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return true; 208d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang} 209d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 2107cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shihbool SoftVPX::outputBufferSafe(OMX_BUFFERHEADERTYPE *outHeader) { 2117cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih uint32_t width = outputBufferWidth(); 2127cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih uint32_t height = outputBufferHeight(); 2137cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih uint64_t nFilledLen = width; 2147cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih nFilledLen *= height; 2157cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih if (nFilledLen > UINT32_MAX / 3) { 216a2c2d1503ccc47b508f726652c714863320cb89bLajos Molnar ALOGE("b/29421675, nFilledLen overflow %llu w %u h %u", 217a2c2d1503ccc47b508f726652c714863320cb89bLajos Molnar (unsigned long long)nFilledLen, width, height); 2187cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih android_errorWriteLog(0x534e4554, "29421675"); 2197cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih return false; 2207cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih } else if (outHeader->nAllocLen < outHeader->nFilledLen) { 2217cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih ALOGE("b/27597103, buffer too small"); 2227cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih android_errorWriteLog(0x534e4554, "27597103"); 2237cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih return false; 2247cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih } 2257cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih 2267cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih return true; 2277cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih} 2287cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih 22984333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) { 230d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (mOutputPortSettingsChange != NONE || mEOSStatus == OUTPUT_FRAMES_FLUSHED) { 231bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return; 232bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 233bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 234bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber List<BufferInfo *> &inQueue = getPortQueue(0); 235bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber List<BufferInfo *> &outQueue = getPortQueue(1); 236a02eae5e911f3bdc3f84f39c0ef223261b646128Lajos Molnar bool EOSseen = false; 237d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang bool portWillReset = false; 238d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 239d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang while ((mEOSStatus == INPUT_EOS_SEEN || !inQueue.empty()) 240d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang && !outQueue.empty()) { 241d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang // Output the pending frames that left from last port reset or decoder flush. 242d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (mEOSStatus == INPUT_EOS_SEEN || mImg != NULL) { 243d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outputBuffers( 244d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus == INPUT_EOS_SEEN, true /* display */, 245d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus == INPUT_EOS_SEEN, &portWillReset)) { 246d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGE("on2 decoder failed to output frame."); 247d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 248d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 249d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 250d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (portWillReset || mEOSStatus == OUTPUT_FRAMES_FLUSHED || 251d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus == INPUT_EOS_SEEN) { 252d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 253d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 2547c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang // Continue as outQueue may be empty now. 2557c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang continue; 256d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 257bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 258bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber BufferInfo *inInfo = *inQueue.begin(); 259bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 260d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian 261d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian // Software VP9 Decoder does not need the Codec Specific Data (CSD) 262d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian // (specified in http://www.webmproject.org/vp9/profiles/). Ignore it if 263d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian // it was passed. 264d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 2655a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang // Only ignore CSD buffer for VP9. 2665a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang if (mMode == MODE_VP9) { 2675a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang inQueue.erase(inQueue.begin()); 2685a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang inInfo->mOwnedByUs = false; 2695a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang notifyEmptyBufferDone(inHeader); 2705a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang continue; 2715a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang } else { 2725a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang // Tolerate the CSD buffer for VP8. This is a workaround 2735a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang // for b/28689536. 2745a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang ALOGW("WARNING: Got CSD buffer for VP8."); 2755a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang } 276d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian } 277d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian 278d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mTimeStamps[mTimeStampIdx] = inHeader->nTimeStamp; 279bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 280bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 281d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus = INPUT_EOS_SEEN; 282a02eae5e911f3bdc3f84f39c0ef223261b646128Lajos Molnar EOSseen = true; 283bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 284bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 2857c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang if (inHeader->nFilledLen > 0) { 2867c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang vpx_codec_err_t err = vpx_codec_decode( 2877c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang (vpx_codec_ctx_t *)mCtx, inHeader->pBuffer + inHeader->nOffset, 2887c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inHeader->nFilledLen, &mTimeStamps[mTimeStampIdx], 0); 2897c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang if (err == VPX_CODEC_OK) { 2907c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inInfo->mOwnedByUs = false; 2917c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inQueue.erase(inQueue.begin()); 2927c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inInfo = NULL; 2937c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang notifyEmptyBufferDone(inHeader); 2947c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inHeader = NULL; 2957c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang } else { 2965a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang ALOGE("on2 decoder failed to decode frame. err: %d", err); 2977c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 2987c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang return; 2997c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang } 300bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 3017c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang 302d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mTimeStampIdx = (mTimeStampIdx + 1) % kNumBuffers; 303bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 304d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outputBuffers( 305d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang EOSseen /* flushDecoder */, true /* display */, EOSseen, &portWillReset)) { 306d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGE("on2 decoder failed to output frame."); 307d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 308d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 309d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 310d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (portWillReset) { 311d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 312bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 313bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 314bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 315bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 316d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuangvoid SoftVPX::onPortFlushCompleted(OMX_U32 portIndex) { 317d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (portIndex == kInputPortIndex) { 318d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang bool portWillReset = false; 319d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outputBuffers( 320d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang true /* flushDecoder */, false /* display */, false /* eos */, &portWillReset)) { 321d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGE("Failed to flush decoder."); 322d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 323d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 324d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 325d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus = INPUT_DATA_AVAILABLE; 326d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 327d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang} 328d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 329d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuangvoid SoftVPX::onReset() { 330d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang bool portWillReset = false; 331d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outputBuffers( 332d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang true /* flushDecoder */, false /* display */, false /* eos */, &portWillReset)) { 333d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGW("Failed to flush decoder. Try to hard reset decoder"); 334d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang destroyDecoder(); 335d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang initDecoder(); 336d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 337d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus = INPUT_DATA_AVAILABLE; 338d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang} 339d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 340bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} // namespace android 341bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 342bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberandroid::SoftOMXComponent *createSoftOMXComponent( 343bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const char *name, const OMX_CALLBACKTYPE *callbacks, 344bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_PTR appData, OMX_COMPONENTTYPE **component) { 34594705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang if (!strcmp(name, "OMX.google.vp8.decoder")) { 34694705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang return new android::SoftVPX( 34794705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang name, "video_decoder.vp8", OMX_VIDEO_CodingVP8, 34894705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang callbacks, appData, component); 34994705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang } else if (!strcmp(name, "OMX.google.vp9.decoder")) { 35094705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang return new android::SoftVPX( 35194705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang name, "video_decoder.vp9", OMX_VIDEO_CodingVP9, 35294705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang callbacks, appData, component); 35394705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang } else { 35494705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang CHECK(!"Unknown component"); 35594705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang } 356dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn return NULL; 357bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 358