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[] = { 339486e0a16e9ad4d4f6bd5047a3cbb1b3f2008d65Hangyu Kuang { OMX_VIDEO_VP9Profile0, OMX_VIDEO_VP9Level5 }, 349486e0a16e9ad4d4f6bd5047a3cbb1b3f2008d65Hangyu Kuang}; 359486e0a16e9ad4d4f6bd5047a3cbb1b3f2008d65Hangyu Kuang 36bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberSoftVPX::SoftVPX( 37bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const char *name, 3894705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang const char *componentRole, 3994705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang OMX_VIDEO_CODINGTYPE codingType, 40bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const OMX_CALLBACKTYPE *callbacks, 41bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_PTR appData, 42bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_COMPONENTTYPE **component) 437f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar : SoftVideoDecoderOMXComponent( 4494705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang name, componentRole, codingType, 459486e0a16e9ad4d4f6bd5047a3cbb1b3f2008d65Hangyu Kuang codingType == OMX_VIDEO_CodingVP8 ? NULL : kVP9ProfileLevels, 469486e0a16e9ad4d4f6bd5047a3cbb1b3f2008d65Hangyu Kuang codingType == OMX_VIDEO_CodingVP8 ? 0 : NELEM(kVP9ProfileLevels), 477f616d3cc5366a4b8af20d3d0c768e3de1df0666Lajos Molnar 320 /* width */, 240 /* height */, callbacks, appData, component), 4894705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang mMode(codingType == OMX_VIDEO_CodingVP8 ? MODE_VP8 : MODE_VP9), 49d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus(INPUT_DATA_AVAILABLE), 5050f939d655a5156157564cb91434f1cce424b2ddhkuang mCtx(NULL), 51d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mFrameParallelMode(false), 52d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mTimeStampIdx(0), 5350f939d655a5156157564cb91434f1cce424b2ddhkuang mImg(NULL) { 54a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar // arbitrary from avc/hevc as vpx does not specify a min compression ratio 55a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar const size_t kMinCompressionRatio = mMode == MODE_VP8 ? 2 : 4; 56a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar const char *mime = mMode == MODE_VP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9; 57a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar const size_t kMaxOutputBufferSize = 2048 * 2048 * 3 / 2; 58a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar initPorts( 59a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar kNumBuffers, kMaxOutputBufferSize / kMinCompressionRatio /* inputBufferSize */, 60a0940a569f2bc24b00dc10ce0fa7658b1dc3a3a5Lajos Molnar kNumBuffers, mime, kMinCompressionRatio); 61bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber CHECK_EQ(initDecoder(), (status_t)OK); 62bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 63bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 64bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberSoftVPX::~SoftVPX() { 65d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang destroyDecoder(); 66bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 67bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 68f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dongstatic int GetCPUCoreCount() { 69f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong int cpuCoreCount = 1; 70f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong#if defined(_SC_NPROCESSORS_ONLN) 71f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN); 72f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong#else 73f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong // _SC_NPROC_ONLN must be defined... 74f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong cpuCoreCount = sysconf(_SC_NPROC_ONLN); 75f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong#endif 76f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong CHECK(cpuCoreCount >= 1); 773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Number of CPU cores: %d", cpuCoreCount); 78f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong return cpuCoreCount; 79f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong} 80f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong 81bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberstatus_t SoftVPX::initDecoder() { 82bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber mCtx = new vpx_codec_ctx_t; 83bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber vpx_codec_err_t vpx_err; 84f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong vpx_codec_dec_cfg_t cfg; 85d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang vpx_codec_flags_t flags; 86f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t)); 87d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang memset(&flags, 0, sizeof(vpx_codec_flags_t)); 88f3ac3e3c94c14dbf1cdf6a4577f0b3aa8edfad06James Dong cfg.threads = GetCPUCoreCount(); 89d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 90d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (mFrameParallelMode) { 91d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang flags |= VPX_CODEC_USE_FRAME_THREADING; 92d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 93d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 94bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber if ((vpx_err = vpx_codec_dec_init( 9594705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang (vpx_codec_ctx_t *)mCtx, 9694705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang mMode == MODE_VP8 ? &vpx_codec_vp8_dx_algo : &vpx_codec_vp9_dx_algo, 97d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang &cfg, flags))) { 9829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("on2 decoder failed to initialize. (%d)", vpx_err); 99bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return UNKNOWN_ERROR; 100bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 101bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 102bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return OK; 103bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 104bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 105d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuangstatus_t SoftVPX::destroyDecoder() { 106d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang vpx_codec_destroy((vpx_codec_ctx_t *)mCtx); 107d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang delete (vpx_codec_ctx_t *)mCtx; 108d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mCtx = NULL; 109d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return OK; 110d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang} 111d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 112d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuangbool SoftVPX::outputBuffers(bool flushDecoder, bool display, bool eos, bool *portWillReset) { 113d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang List<BufferInfo *> &outQueue = getPortQueue(1); 114d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang BufferInfo *outInfo = NULL; 115d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang OMX_BUFFERHEADERTYPE *outHeader = NULL; 116d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang vpx_codec_iter_t iter = NULL; 117d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 118d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (flushDecoder && mFrameParallelMode) { 119d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang // Flush decoder by passing NULL data ptr and 0 size. 120d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang // Ideally, this should never fail. 121d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (vpx_codec_decode((vpx_codec_ctx_t *)mCtx, NULL, 0, NULL, 0)) { 122d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGE("Failed to flush on2 decoder."); 123d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return false; 124d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 125d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 126d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 127d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!display) { 128d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!flushDecoder) { 129d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGE("Invalid operation."); 130d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return false; 131d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 132d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang // Drop all the decoded frames in decoder. 133d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang while ((mImg = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter))) { 134d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 135d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return true; 136d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 137d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 138d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang while (!outQueue.empty()) { 139d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (mImg == NULL) { 140d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mImg = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter); 141d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (mImg == NULL) { 142d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang break; 143d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 144d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 145d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang uint32_t width = mImg->d_w; 146d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang uint32_t height = mImg->d_h; 147d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo = *outQueue.begin(); 148d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader = outInfo->mHeader; 149252e0d8ae9fae7711800dac01bd851a3ebc23135Johann CHECK_EQ(mImg->fmt, VPX_IMG_FMT_I420); 150d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang handlePortSettingsChange(portWillReset, width, height); 151d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (*portWillReset) { 152d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return true; 153d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 154d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 155d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nOffset = 0; 156d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nFlags = 0; 1573ecc9db40b1fb9c7f807a5892e5c9625aac1fb06Marco Nelissen outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2; 158d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nTimeStamp = *(OMX_TICKS *)mImg->user_priv; 1597cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih if (outputBufferSafe(outHeader)) { 160ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen uint8_t *dst = outHeader->pBuffer; 161ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen const uint8_t *srcY = (const uint8_t *)mImg->planes[VPX_PLANE_Y]; 162ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen const uint8_t *srcU = (const uint8_t *)mImg->planes[VPX_PLANE_U]; 163ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen const uint8_t *srcV = (const uint8_t *)mImg->planes[VPX_PLANE_V]; 164ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen size_t srcYStride = mImg->stride[VPX_PLANE_Y]; 165ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen size_t srcUStride = mImg->stride[VPX_PLANE_U]; 166ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen size_t srcVStride = mImg->stride[VPX_PLANE_V]; 167ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride); 168ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen } else { 169ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen outHeader->nFilledLen = 0; 170ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen } 171d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 172d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mImg = NULL; 173d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo->mOwnedByUs = false; 174d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outQueue.erase(outQueue.begin()); 175d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo = NULL; 176d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notifyFillBufferDone(outHeader); 177d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader = NULL; 178d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 179d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 180d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!eos) { 181d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return true; 182d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 183d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 184d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outQueue.empty()) { 185d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo = *outQueue.begin(); 186d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outQueue.erase(outQueue.begin()); 187d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader = outInfo->mHeader; 188d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nTimeStamp = 0; 189d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nFilledLen = 0; 190d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nFlags = OMX_BUFFERFLAG_EOS; 191d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo->mOwnedByUs = false; 192d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notifyFillBufferDone(outHeader); 193d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus = OUTPUT_FRAMES_FLUSHED; 194d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 195d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return true; 196d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang} 197d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 1987cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shihbool SoftVPX::outputBufferSafe(OMX_BUFFERHEADERTYPE *outHeader) { 1997cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih uint32_t width = outputBufferWidth(); 2007cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih uint32_t height = outputBufferHeight(); 2017cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih uint64_t nFilledLen = width; 2027cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih nFilledLen *= height; 2037cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih if (nFilledLen > UINT32_MAX / 3) { 204a2c2d1503ccc47b508f726652c714863320cb89bLajos Molnar ALOGE("b/29421675, nFilledLen overflow %llu w %u h %u", 205a2c2d1503ccc47b508f726652c714863320cb89bLajos Molnar (unsigned long long)nFilledLen, width, height); 2067cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih android_errorWriteLog(0x534e4554, "29421675"); 2077cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih return false; 2087cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih } else if (outHeader->nAllocLen < outHeader->nFilledLen) { 2097cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih ALOGE("b/27597103, buffer too small"); 2107cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih android_errorWriteLog(0x534e4554, "27597103"); 2117cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih return false; 2127cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih } 2137cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih 2147cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih return true; 2157cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih} 2167cfc18e680fc295d1975c8da183f0d9df4cab803Robert Shih 21784333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) { 218d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (mOutputPortSettingsChange != NONE || mEOSStatus == OUTPUT_FRAMES_FLUSHED) { 219bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return; 220bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 221bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 222bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber List<BufferInfo *> &inQueue = getPortQueue(0); 223bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber List<BufferInfo *> &outQueue = getPortQueue(1); 224a02eae5e911f3bdc3f84f39c0ef223261b646128Lajos Molnar bool EOSseen = false; 225d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang bool portWillReset = false; 226d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 227d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang while ((mEOSStatus == INPUT_EOS_SEEN || !inQueue.empty()) 228d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang && !outQueue.empty()) { 229d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang // Output the pending frames that left from last port reset or decoder flush. 230d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (mEOSStatus == INPUT_EOS_SEEN || mImg != NULL) { 231d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outputBuffers( 232d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus == INPUT_EOS_SEEN, true /* display */, 233d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus == INPUT_EOS_SEEN, &portWillReset)) { 234d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGE("on2 decoder failed to output frame."); 235d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 236d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 237d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 238d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (portWillReset || mEOSStatus == OUTPUT_FRAMES_FLUSHED || 239d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus == INPUT_EOS_SEEN) { 240d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 241d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 2427c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang // Continue as outQueue may be empty now. 2437c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang continue; 244d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 245bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 246bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber BufferInfo *inInfo = *inQueue.begin(); 247bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 248d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian 249d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian // Software VP9 Decoder does not need the Codec Specific Data (CSD) 250d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian // (specified in http://www.webmproject.org/vp9/profiles/). Ignore it if 251d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian // it was passed. 252d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 2535a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang // Only ignore CSD buffer for VP9. 2545a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang if (mMode == MODE_VP9) { 2555a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang inQueue.erase(inQueue.begin()); 2565a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang inInfo->mOwnedByUs = false; 2575a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang notifyEmptyBufferDone(inHeader); 2585a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang continue; 2595a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang } else { 2605a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang // Tolerate the CSD buffer for VP8. This is a workaround 2615a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang // for b/28689536. 2625a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang ALOGW("WARNING: Got CSD buffer for VP8."); 2635a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang } 264d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian } 265d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian 266d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mTimeStamps[mTimeStampIdx] = inHeader->nTimeStamp; 267bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 268bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 269d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus = INPUT_EOS_SEEN; 270a02eae5e911f3bdc3f84f39c0ef223261b646128Lajos Molnar EOSseen = true; 271bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 272bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 2737c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang if (inHeader->nFilledLen > 0) { 2747c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang vpx_codec_err_t err = vpx_codec_decode( 2757c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang (vpx_codec_ctx_t *)mCtx, inHeader->pBuffer + inHeader->nOffset, 2767c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inHeader->nFilledLen, &mTimeStamps[mTimeStampIdx], 0); 2777c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang if (err == VPX_CODEC_OK) { 2787c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inInfo->mOwnedByUs = false; 2797c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inQueue.erase(inQueue.begin()); 2807c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inInfo = NULL; 2817c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang notifyEmptyBufferDone(inHeader); 2827c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inHeader = NULL; 2837c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang } else { 2845a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang ALOGE("on2 decoder failed to decode frame. err: %d", err); 2857c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 2867c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang return; 2877c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang } 288bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 2897c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang 290d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mTimeStampIdx = (mTimeStampIdx + 1) % kNumBuffers; 291bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 292d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outputBuffers( 293d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang EOSseen /* flushDecoder */, true /* display */, EOSseen, &portWillReset)) { 294d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGE("on2 decoder failed to output frame."); 295d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 296d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 297d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 298d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (portWillReset) { 299d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 300bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 301bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 302bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 303bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 304d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuangvoid SoftVPX::onPortFlushCompleted(OMX_U32 portIndex) { 305d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (portIndex == kInputPortIndex) { 306d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang bool portWillReset = false; 307d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outputBuffers( 308d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang true /* flushDecoder */, false /* display */, false /* eos */, &portWillReset)) { 309d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGE("Failed to flush decoder."); 310d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 311d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 312d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 313d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus = INPUT_DATA_AVAILABLE; 314d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 315d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang} 316d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 317d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuangvoid SoftVPX::onReset() { 318d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang bool portWillReset = false; 319d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outputBuffers( 320d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang true /* flushDecoder */, false /* display */, false /* eos */, &portWillReset)) { 321d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGW("Failed to flush decoder. Try to hard reset decoder"); 322d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang destroyDecoder(); 323d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang initDecoder(); 324d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 325d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus = INPUT_DATA_AVAILABLE; 326d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang} 327d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 328bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} // namespace android 329bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 330bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberandroid::SoftOMXComponent *createSoftOMXComponent( 331bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const char *name, const OMX_CALLBACKTYPE *callbacks, 332bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_PTR appData, OMX_COMPONENTTYPE **component) { 33394705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang if (!strcmp(name, "OMX.google.vp8.decoder")) { 33494705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang return new android::SoftVPX( 33594705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang name, "video_decoder.vp8", OMX_VIDEO_CodingVP8, 33694705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang callbacks, appData, component); 33794705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang } else if (!strcmp(name, "OMX.google.vp9.decoder")) { 33894705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang return new android::SoftVPX( 33994705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang name, "video_decoder.vp9", OMX_VIDEO_CodingVP9, 34094705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang callbacks, appData, component); 34194705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang } else { 34294705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang CHECK(!"Unknown component"); 34394705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang } 344dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn return NULL; 345bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 346