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; 159ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen if (outHeader->nAllocLen >= outHeader->nFilledLen) { 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 ALOGE("b/27597103, buffer too small"); 170ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen android_errorWriteLog(0x534e4554, "27597103"); 171ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen outHeader->nFilledLen = 0; 172ca00182c94d2ec1bdc9baeb1385e0cf3de9171d1Marco Nelissen } 173d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 174d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mImg = NULL; 175d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo->mOwnedByUs = false; 176d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outQueue.erase(outQueue.begin()); 177d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo = NULL; 178d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notifyFillBufferDone(outHeader); 179d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader = NULL; 180d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 181d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 182d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!eos) { 183d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return true; 184d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 185d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 186d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outQueue.empty()) { 187d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo = *outQueue.begin(); 188d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outQueue.erase(outQueue.begin()); 189d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader = outInfo->mHeader; 190d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nTimeStamp = 0; 191d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nFilledLen = 0; 192d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outHeader->nFlags = OMX_BUFFERFLAG_EOS; 193d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang outInfo->mOwnedByUs = false; 194d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notifyFillBufferDone(outHeader); 195d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus = OUTPUT_FRAMES_FLUSHED; 196d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 197d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return true; 198d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang} 199d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 20084333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) { 201d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (mOutputPortSettingsChange != NONE || mEOSStatus == OUTPUT_FRAMES_FLUSHED) { 202bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return; 203bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 204bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 205bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber List<BufferInfo *> &inQueue = getPortQueue(0); 206bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber List<BufferInfo *> &outQueue = getPortQueue(1); 207a02eae5e911f3bdc3f84f39c0ef223261b646128Lajos Molnar bool EOSseen = false; 208d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang bool portWillReset = false; 209d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 210d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang while ((mEOSStatus == INPUT_EOS_SEEN || !inQueue.empty()) 211d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang && !outQueue.empty()) { 212d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang // Output the pending frames that left from last port reset or decoder flush. 213d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (mEOSStatus == INPUT_EOS_SEEN || mImg != NULL) { 214d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outputBuffers( 215d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus == INPUT_EOS_SEEN, true /* display */, 216d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus == INPUT_EOS_SEEN, &portWillReset)) { 217d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGE("on2 decoder failed to output frame."); 218d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 219d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 220d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 221d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (portWillReset || mEOSStatus == OUTPUT_FRAMES_FLUSHED || 222d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus == INPUT_EOS_SEEN) { 223d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 224d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 2257c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang // Continue as outQueue may be empty now. 2267c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang continue; 227d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 228bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 229bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber BufferInfo *inInfo = *inQueue.begin(); 230bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 231d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian 232d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian // Software VP9 Decoder does not need the Codec Specific Data (CSD) 233d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian // (specified in http://www.webmproject.org/vp9/profiles/). Ignore it if 234d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian // it was passed. 235d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 2365a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang // Only ignore CSD buffer for VP9. 2375a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang if (mMode == MODE_VP9) { 2385a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang inQueue.erase(inQueue.begin()); 2395a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang inInfo->mOwnedByUs = false; 2405a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang notifyEmptyBufferDone(inHeader); 2415a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang continue; 2425a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang } else { 2435a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang // Tolerate the CSD buffer for VP8. This is a workaround 2445a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang // for b/28689536. 2455a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang ALOGW("WARNING: Got CSD buffer for VP8."); 2465a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang } 247d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian } 248d0d32c0d39b56d7e85fcaa61f3245ac7bbb1f9ebVignesh Venkatasubramanian 249d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mTimeStamps[mTimeStampIdx] = inHeader->nTimeStamp; 250bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 251bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 252d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus = INPUT_EOS_SEEN; 253a02eae5e911f3bdc3f84f39c0ef223261b646128Lajos Molnar EOSseen = true; 254bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 255bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 2567c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang if (inHeader->nFilledLen > 0) { 2577c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang vpx_codec_err_t err = vpx_codec_decode( 2587c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang (vpx_codec_ctx_t *)mCtx, inHeader->pBuffer + inHeader->nOffset, 2597c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inHeader->nFilledLen, &mTimeStamps[mTimeStampIdx], 0); 2607c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang if (err == VPX_CODEC_OK) { 2617c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inInfo->mOwnedByUs = false; 2627c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inQueue.erase(inQueue.begin()); 2637c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inInfo = NULL; 2647c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang notifyEmptyBufferDone(inHeader); 2657c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang inHeader = NULL; 2667c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang } else { 2675a25d9382cc96f56c6f178c11313eb26ad7000ccHangyu Kuang ALOGE("on2 decoder failed to decode frame. err: %d", err); 2687c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 2697c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang return; 2707c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang } 271bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 2727c98ddc18d699660bf89df598fb2c13870e85aaeHangyu Kuang 273d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mTimeStampIdx = (mTimeStampIdx + 1) % kNumBuffers; 274bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 275d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outputBuffers( 276d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang EOSseen /* flushDecoder */, true /* display */, EOSseen, &portWillReset)) { 277d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGE("on2 decoder failed to output frame."); 278d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 279d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 280d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 281d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (portWillReset) { 282d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 283bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 284bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 285bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 286bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 287d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuangvoid SoftVPX::onPortFlushCompleted(OMX_U32 portIndex) { 288d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (portIndex == kInputPortIndex) { 289d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang bool portWillReset = false; 290d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outputBuffers( 291d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang true /* flushDecoder */, false /* display */, false /* eos */, &portWillReset)) { 292d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGE("Failed to flush decoder."); 293d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 294d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang return; 295d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 296d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus = INPUT_DATA_AVAILABLE; 297d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 298d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang} 299d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 300d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuangvoid SoftVPX::onReset() { 301d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang bool portWillReset = false; 302d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang if (!outputBuffers( 303d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang true /* flushDecoder */, false /* display */, false /* eos */, &portWillReset)) { 304d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang ALOGW("Failed to flush decoder. Try to hard reset decoder"); 305d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang destroyDecoder(); 306d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang initDecoder(); 307d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang } 308d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang mEOSStatus = INPUT_DATA_AVAILABLE; 309d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang} 310d42b90c5183fbd9d6a28d9baee613fddbf8131d6hkuang 311bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} // namespace android 312bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 313bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberandroid::SoftOMXComponent *createSoftOMXComponent( 314bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const char *name, const OMX_CALLBACKTYPE *callbacks, 315bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_PTR appData, OMX_COMPONENTTYPE **component) { 31694705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang if (!strcmp(name, "OMX.google.vp8.decoder")) { 31794705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang return new android::SoftVPX( 31894705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang name, "video_decoder.vp8", OMX_VIDEO_CodingVP8, 31994705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang callbacks, appData, component); 32094705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang } else if (!strcmp(name, "OMX.google.vp9.decoder")) { 32194705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang return new android::SoftVPX( 32294705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang name, "video_decoder.vp9", OMX_VIDEO_CodingVP9, 32394705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang callbacks, appData, component); 32494705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang } else { 32594705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang CHECK(!"Unknown component"); 32694705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang } 327dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7Mark Salyzyn return NULL; 328bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 329