SoftVPX.cpp revision dba83c1cb1bef03bc5d1760c2639d06ff71c0fa7
18a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen/* 28a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen * Copyright (C) 2011 The Android Open Source Project 38a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen * 48a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen * Licensed under the Apache License, Version 2.0 (the "License"); 58a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen * you may not use this file except in compliance with the License. 68a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen * You may obtain a copy of the License at 78a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen * 88a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen * http://www.apache.org/licenses/LICENSE-2.0 98a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen * 108a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen * Unless required by applicable law or agreed to in writing, software 118a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen * distributed under the License is distributed on an "AS IS" BASIS, 128a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen * See the License for the specific language governing permissions and 148a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen * limitations under the License. 158a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen */ 168a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 178a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen//#define LOG_NDEBUG 0 188a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#define LOG_TAG "SoftVPX" 198a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#include <utils/Log.h> 208a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 218a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#include "SoftVPX.h" 228a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 238a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#include <media/stagefright/foundation/ADebug.h> 248a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#include <media/stagefright/MediaDefs.h> 258a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 268a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 278a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chennamespace android { 288a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 298a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny ChenSoftVPX::SoftVPX( 308a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen const char *name, 318a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen const char *componentRole, 328a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen OMX_VIDEO_CODINGTYPE codingType, 338a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen const OMX_CALLBACKTYPE *callbacks, 348a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen OMX_PTR appData, 358a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen OMX_COMPONENTTYPE **component) 368a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen : SoftVideoDecoderOMXComponent( 378a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen name, componentRole, codingType, 388a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen NULL /* profileLevels */, 0 /* numProfileLevels */, 398a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 320 /* width */, 240 /* height */, callbacks, appData, component), 408a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen mMode(codingType == OMX_VIDEO_CodingVP8 ? MODE_VP8 : MODE_VP9), 418a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen mCtx(NULL), 428a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen mImg(NULL) { 438a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen initPorts(kNumBuffers, 768 * 1024 /* inputBufferSize */, 448a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen kNumBuffers, 458a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen codingType == OMX_VIDEO_CodingVP8 ? MEDIA_MIMETYPE_VIDEO_VP8 : MEDIA_MIMETYPE_VIDEO_VP9); 468a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 478a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen CHECK_EQ(initDecoder(), (status_t)OK); 488a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen} 498a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 508a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny ChenSoftVPX::~SoftVPX() { 518a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen vpx_codec_destroy((vpx_codec_ctx_t *)mCtx); 528a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen delete (vpx_codec_ctx_t *)mCtx; 538a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen mCtx = NULL; 548a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen} 558a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 568a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenstatic int GetCPUCoreCount() { 578a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen int cpuCoreCount = 1; 588a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#if defined(_SC_NPROCESSORS_ONLN) 598a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN); 608a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#else 618a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen // _SC_NPROC_ONLN must be defined... 628a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen cpuCoreCount = sysconf(_SC_NPROC_ONLN); 638a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen#endif 648a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen CHECK(cpuCoreCount >= 1); 658a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen ALOGV("Number of CPU cores: %d", cpuCoreCount); 668a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen return cpuCoreCount; 678a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen} 688a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 698a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenstatus_t SoftVPX::initDecoder() { 708a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen mCtx = new vpx_codec_ctx_t; 718a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen vpx_codec_err_t vpx_err; 728a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen vpx_codec_dec_cfg_t cfg; 738a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t)); 748a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen cfg.threads = GetCPUCoreCount(); 758a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen if ((vpx_err = vpx_codec_dec_init( 768a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen (vpx_codec_ctx_t *)mCtx, 778a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen mMode == MODE_VP8 ? &vpx_codec_vp8_dx_algo : &vpx_codec_vp9_dx_algo, 788a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen &cfg, 0))) { 798a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen ALOGE("on2 decoder failed to initialize. (%d)", vpx_err); 808a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen return UNKNOWN_ERROR; 818a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen } 828a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 838a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen return OK; 848a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen} 858a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 868a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chenvoid SoftVPX::onQueueFilled(OMX_U32 /* portIndex */) { 878a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen if (mOutputPortSettingsChange != NONE) { 888a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen return; 898a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen } 908a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 918a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen List<BufferInfo *> &inQueue = getPortQueue(0); 928a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen List<BufferInfo *> &outQueue = getPortQueue(1); 938a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen bool EOSseen = false; 948a3c0430323c28c1fbe8ceecd2cd8e58b64a9295Johnny Chen 95 while (!inQueue.empty() && !outQueue.empty()) { 96 BufferInfo *inInfo = *inQueue.begin(); 97 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 98 99 BufferInfo *outInfo = *outQueue.begin(); 100 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 101 102 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 103 EOSseen = true; 104 if (inHeader->nFilledLen == 0) { 105 inQueue.erase(inQueue.begin()); 106 inInfo->mOwnedByUs = false; 107 notifyEmptyBufferDone(inHeader); 108 109 outHeader->nFilledLen = 0; 110 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 111 112 outQueue.erase(outQueue.begin()); 113 outInfo->mOwnedByUs = false; 114 notifyFillBufferDone(outHeader); 115 return; 116 } 117 } 118 119 if (mImg == NULL) { 120 if (vpx_codec_decode( 121 (vpx_codec_ctx_t *)mCtx, 122 inHeader->pBuffer + inHeader->nOffset, 123 inHeader->nFilledLen, 124 NULL, 125 0)) { 126 ALOGE("on2 decoder failed to decode frame."); 127 128 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 129 return; 130 } 131 vpx_codec_iter_t iter = NULL; 132 mImg = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter); 133 } 134 135 if (mImg != NULL) { 136 CHECK_EQ(mImg->fmt, IMG_FMT_I420); 137 138 uint32_t width = mImg->d_w; 139 uint32_t height = mImg->d_h; 140 bool portWillReset = false; 141 handlePortSettingsChange(&portWillReset, width, height); 142 if (portWillReset) { 143 return; 144 } 145 146 outHeader->nOffset = 0; 147 outHeader->nFilledLen = (width * height * 3) / 2; 148 outHeader->nFlags = EOSseen ? OMX_BUFFERFLAG_EOS : 0; 149 outHeader->nTimeStamp = inHeader->nTimeStamp; 150 151 uint8_t *dst = outHeader->pBuffer; 152 const uint8_t *srcY = (const uint8_t *)mImg->planes[PLANE_Y]; 153 const uint8_t *srcU = (const uint8_t *)mImg->planes[PLANE_U]; 154 const uint8_t *srcV = (const uint8_t *)mImg->planes[PLANE_V]; 155 size_t srcYStride = mImg->stride[PLANE_Y]; 156 size_t srcUStride = mImg->stride[PLANE_U]; 157 size_t srcVStride = mImg->stride[PLANE_V]; 158 copyYV12FrameToOutputBuffer(dst, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride); 159 160 mImg = NULL; 161 outInfo->mOwnedByUs = false; 162 outQueue.erase(outQueue.begin()); 163 outInfo = NULL; 164 notifyFillBufferDone(outHeader); 165 outHeader = NULL; 166 } 167 168 inInfo->mOwnedByUs = false; 169 inQueue.erase(inQueue.begin()); 170 inInfo = NULL; 171 notifyEmptyBufferDone(inHeader); 172 inHeader = NULL; 173 } 174} 175 176} // namespace android 177 178android::SoftOMXComponent *createSoftOMXComponent( 179 const char *name, const OMX_CALLBACKTYPE *callbacks, 180 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 181 if (!strcmp(name, "OMX.google.vp8.decoder")) { 182 return new android::SoftVPX( 183 name, "video_decoder.vp8", OMX_VIDEO_CodingVP8, 184 callbacks, appData, component); 185 } else if (!strcmp(name, "OMX.google.vp9.decoder")) { 186 return new android::SoftVPX( 187 name, "video_decoder.vp9", OMX_VIDEO_CodingVP9, 188 callbacks, appData, component); 189 } else { 190 CHECK(!"Unknown component"); 191 } 192 return NULL; 193} 194