SoftAVC.cpp revision d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2
15bc087c573c70c84c6a39946457590b42d392a33Andreas Huber/* 25bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * Copyright (C) 2011 The Android Open Source Project 35bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * 45bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 55bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * you may not use this file except in compliance with the License. 65bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * You may obtain a copy of the License at 75bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * 85bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 95bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * 105bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * Unless required by applicable law or agreed to in writing, software 115bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 125bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * See the License for the specific language governing permissions and 145bc087c573c70c84c6a39946457590b42d392a33Andreas Huber * limitations under the License. 155bc087c573c70c84c6a39946457590b42d392a33Andreas Huber */ 165bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 175bc087c573c70c84c6a39946457590b42d392a33Andreas Huber//#define LOG_NDEBUG 0 185bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#define LOG_TAG "SoftAVC" 195bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <utils/Log.h> 205bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 215bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include "SoftAVC.h" 225bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 235bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/foundation/ADebug.h> 245bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/MediaDefs.h> 255bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/stagefright/MediaErrors.h> 265bc087c573c70c84c6a39946457590b42d392a33Andreas Huber#include <media/IOMX.h> 275bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 285bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 295bc087c573c70c84c6a39946457590b42d392a33Andreas Hubernamespace android { 305bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 315bc087c573c70c84c6a39946457590b42d392a33Andreas Huberstatic const CodecProfileLevel kProfileLevels[] = { 32093024bfa271988655327e0fb761b581afa8bc11Robert Shih { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1 }, 335bc087c573c70c84c6a39946457590b42d392a33Andreas Huber { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b }, 345bc087c573c70c84c6a39946457590b42d392a33Andreas Huber { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11 }, 355bc087c573c70c84c6a39946457590b42d392a33Andreas Huber { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12 }, 368cf4ced8d25e9b1b56b69b544339acc1550e4038osamu fujita { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13 }, 378cf4ced8d25e9b1b56b69b544339acc1550e4038osamu fujita { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2 }, 38b5f25f005bc1d3ae35f45b58c88345e183dc336dAndreas Huber { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21 }, 39b5f25f005bc1d3ae35f45b58c88345e183dc336dAndreas Huber { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22 }, 40b5f25f005bc1d3ae35f45b58c88345e183dc336dAndreas Huber { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3 }, 41b5f25f005bc1d3ae35f45b58c88345e183dc336dAndreas Huber { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31 }, 42b5f25f005bc1d3ae35f45b58c88345e183dc336dAndreas Huber { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel32 }, 43180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel4 }, 44180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 }, 455bc087c573c70c84c6a39946457590b42d392a33Andreas Huber { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel42 }, 465bc087c573c70c84c6a39946457590b42d392a33Andreas Huber { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel5 }, 475bc087c573c70c84c6a39946457590b42d392a33Andreas Huber { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel51 }, 48180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang}; 49180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 50180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhangtemplate<class T> 51180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhangstatic void InitOMXParams(T *params) { 525bc087c573c70c84c6a39946457590b42d392a33Andreas Huber params->nSize = sizeof(T); 535bc087c573c70c84c6a39946457590b42d392a33Andreas Huber params->nVersion.s.nVersionMajor = 1; 549575c96b6e418914e2ffc6741ecc8d71e3968dbeAndreas Huber params->nVersion.s.nVersionMinor = 0; 55180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang params->nVersion.s.nRevision = 0; 56180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang params->nVersion.s.nStep = 0; 57180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang} 58180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 59180d1b96ee2312f1056a58e26884a89d25ab62c8Chong ZhangSoftAVC::SoftAVC( 60180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang const char *name, 61180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang const OMX_CALLBACKTYPE *callbacks, 62180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang OMX_PTR appData, 63ced1c2f8f6c422063092f5cc5c675ccdebb2dc10Chong Zhang OMX_COMPONENTTYPE **component) 649575c96b6e418914e2ffc6741ecc8d71e3968dbeAndreas Huber : SimpleSoftOMXComponent(name, callbacks, appData, component), 659575c96b6e418914e2ffc6741ecc8d71e3968dbeAndreas Huber mHandle(NULL), 669575c96b6e418914e2ffc6741ecc8d71e3968dbeAndreas Huber mInputBufferCount(0), 679575c96b6e418914e2ffc6741ecc8d71e3968dbeAndreas Huber mWidth(320), 685bc087c573c70c84c6a39946457590b42d392a33Andreas Huber mHeight(240), 691d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar mPictureSize(mWidth * mHeight * 3 / 2), 7087f2a558dd12043631e12c361abef301bf603140Andreas Huber mCropLeft(0), 7187f2a558dd12043631e12c361abef301bf603140Andreas Huber mCropTop(0), 7287f2a558dd12043631e12c361abef301bf603140Andreas Huber mCropWidth(mWidth), 7387f2a558dd12043631e12c361abef301bf603140Andreas Huber mCropHeight(mHeight), 7487f2a558dd12043631e12c361abef301bf603140Andreas Huber mFirstPicture(NULL), 7587f2a558dd12043631e12c361abef301bf603140Andreas Huber mFirstPictureId(-1), 7687f2a558dd12043631e12c361abef301bf603140Andreas Huber mPicId(0), 7787f2a558dd12043631e12c361abef301bf603140Andreas Huber mHeadersDecoded(false), 7887f2a558dd12043631e12c361abef301bf603140Andreas Huber mEOSStatus(INPUT_DATA_AVAILABLE), 795bc087c573c70c84c6a39946457590b42d392a33Andreas Huber mOutputPortSettingsChange(NONE), 805bc087c573c70c84c6a39946457590b42d392a33Andreas Huber mSignalledError(false) { 81180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang initPorts(); 82180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang CHECK_EQ(initDecoder(), (status_t)OK); 835bc087c573c70c84c6a39946457590b42d392a33Andreas Huber} 845bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 85eac68baf095aeef54865c28b6888924dc6295cbdAndreas HuberSoftAVC::~SoftAVC() { 86180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang H264SwDecRelease(mHandle); 87180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang mHandle = NULL; 885bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 89180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang while (mPicToHeaderMap.size() != 0) { 908cf4ced8d25e9b1b56b69b544339acc1550e4038osamu fujita OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.editValueAt(0); 915bc087c573c70c84c6a39946457590b42d392a33Andreas Huber mPicToHeaderMap.removeItemsAt(0); 9232f3cefa373cd55e63deda36ca9d07c7fe22eaafAndreas Huber delete header; 9332f3cefa373cd55e63deda36ca9d07c7fe22eaafAndreas Huber header = NULL; 945bc087c573c70c84c6a39946457590b42d392a33Andreas Huber } 955bc087c573c70c84c6a39946457590b42d392a33Andreas Huber List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex); 96df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex); 975bc087c573c70c84c6a39946457590b42d392a33Andreas Huber CHECK(outQueue.empty()); 98180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang CHECK(inQueue.empty()); 995bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 1005bc087c573c70c84c6a39946457590b42d392a33Andreas Huber delete[] mFirstPicture; 101fef808d42a9c94b0b5ef3c3d5fb0a090edbc42daWei Jia} 10242e549e4ab54802d788c43e3a04a85b7a1a95e97Andreas Huber 103bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Hubervoid SoftAVC::initPorts() { 10442e549e4ab54802d788c43e3a04a85b7a1a95e97Andreas Huber OMX_PARAM_PORTDEFINITIONTYPE def; 10542e549e4ab54802d788c43e3a04a85b7a1a95e97Andreas Huber InitOMXParams(&def); 106bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber 107bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber def.nPortIndex = kInputPortIndex; 10829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block def.eDir = OMX_DirInput; 109180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang def.nBufferCountMin = kNumInputBuffers; 110180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang def.nBufferCountActual = def.nBufferCountMin; 111bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber def.nBufferSize = 8192; 112bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber def.bEnabled = OMX_TRUE; 113bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber def.bPopulated = OMX_FALSE; 11442e549e4ab54802d788c43e3a04a85b7a1a95e97Andreas Huber def.eDomain = OMX_PortDomainVideo; 11542e549e4ab54802d788c43e3a04a85b7a1a95e97Andreas Huber def.bBuffersContiguous = OMX_FALSE; 116bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber def.nBufferAlignment = 1; 117bfcc8d8ab7c56bc013bd221a29e1ecf3a6390813Andreas Huber 1185bc087c573c70c84c6a39946457590b42d392a33Andreas Huber def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_AVC); 1195bc087c573c70c84c6a39946457590b42d392a33Andreas Huber def.format.video.pNativeRender = NULL; 1205bc087c573c70c84c6a39946457590b42d392a33Andreas Huber def.format.video.nFrameWidth = mWidth; 1215bc087c573c70c84c6a39946457590b42d392a33Andreas Huber def.format.video.nFrameHeight = mHeight; 1225bc087c573c70c84c6a39946457590b42d392a33Andreas Huber def.format.video.nStride = def.format.video.nFrameWidth; 123b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber def.format.video.nSliceHeight = def.format.video.nFrameHeight; 124b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber def.format.video.nBitrate = 0; 125b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber def.format.video.xFramerate = 0; 126b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber def.format.video.bFlagErrorConcealment = OMX_FALSE; 127b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; 128b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber def.format.video.eColorFormat = OMX_COLOR_FormatUnused; 129b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber def.format.video.pNativeWindow = NULL; 130b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 131b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber addPort(def); 132b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber 133b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber def.nPortIndex = kOutputPortIndex; 134b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber def.eDir = OMX_DirOutput; 135b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber def.nBufferCountMin = kNumOutputBuffers; 136b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber def.nBufferCountActual = def.nBufferCountMin; 1375bc087c573c70c84c6a39946457590b42d392a33Andreas Huber def.bEnabled = OMX_TRUE; 138b7c8e91880463ff4981e3e53e98e45d68e2fe374Andreas Huber def.bPopulated = OMX_FALSE; 139fef808d42a9c94b0b5ef3c3d5fb0a090edbc42daWei Jia def.eDomain = OMX_PortDomainVideo; 14032f3cefa373cd55e63deda36ca9d07c7fe22eaafAndreas Huber def.bBuffersContiguous = OMX_FALSE; 14132f3cefa373cd55e63deda36ca9d07c7fe22eaafAndreas Huber def.nBufferAlignment = 2; 1425bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 14306528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW); 14406528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber def.format.video.pNativeRender = NULL; 14506528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber def.format.video.nFrameWidth = mWidth; 14629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block def.format.video.nFrameHeight = mHeight; 14706528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber def.format.video.nStride = def.format.video.nFrameWidth; 14806528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber def.format.video.nSliceHeight = def.format.video.nFrameHeight; 149180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang def.format.video.nBitrate = 0; 15006528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber def.format.video.xFramerate = 0; 15106528d7f18ad01377357d337eaa3e875a242bd2dAndreas Huber def.format.video.bFlagErrorConcealment = OMX_FALSE; 1525bc087c573c70c84c6a39946457590b42d392a33Andreas Huber def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; 1535bc087c573c70c84c6a39946457590b42d392a33Andreas Huber def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; 1545bc087c573c70c84c6a39946457590b42d392a33Andreas Huber def.format.video.pNativeWindow = NULL; 155180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 156180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang def.nBufferSize = 157180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2; 158180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 159180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang addPort(def); 160180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang} 161180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 162180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhangstatus_t SoftAVC::initDecoder() { 163180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang // Force decoder to output buffers in display order. 164180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (H264SwDecInit(&mHandle, 0) == H264SWDEC_OK) { 165180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return OK; 166180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 167180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return UNKNOWN_ERROR; 1685bc087c573c70c84c6a39946457590b42d392a33Andreas Huber} 1691d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar 170eac68baf095aeef54865c28b6888924dc6295cbdAndreas HuberOMX_ERRORTYPE SoftAVC::internalGetParameter( 1715bc087c573c70c84c6a39946457590b42d392a33Andreas Huber OMX_INDEXTYPE index, OMX_PTR params) { 1725bc087c573c70c84c6a39946457590b42d392a33Andreas Huber switch (index) { 173180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang case OMX_IndexParamVideoPortFormat: 174180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang { 175180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = 176180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; 177180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 178180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (formatParams->nPortIndex > kOutputPortIndex) { 179180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return OMX_ErrorUndefined; 180180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 181180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 182180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (formatParams->nIndex != 0) { 183180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return OMX_ErrorNoMore; 184180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 185180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 186180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (formatParams->nPortIndex == kInputPortIndex) { 187180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC; 188180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang formatParams->eColorFormat = OMX_COLOR_FormatUnused; 189180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang formatParams->xFramerate = 0; 190180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } else { 191180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang CHECK(formatParams->nPortIndex == kOutputPortIndex); 192180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 193180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused; 194180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar; 195180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang formatParams->xFramerate = 0; 196180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 197180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 198180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return OMX_ErrorNone; 199180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 200180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 201180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang case OMX_IndexParamVideoProfileLevelQuerySupported: 202180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang { 203180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel = 204180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params; 205180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 206180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (profileLevel->nPortIndex != kInputPortIndex) { 207180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang ALOGE("Invalid port index: %ld", profileLevel->nPortIndex); 208180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return OMX_ErrorUnsupportedIndex; 209180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 210180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 211ab05b4ccb8ea59079d7f773aa0e090029c479badWei Jia size_t index = profileLevel->nProfileIndex; 212ab05b4ccb8ea59079d7f773aa0e090029c479badWei Jia size_t nProfileLevels = 213ab05b4ccb8ea59079d7f773aa0e090029c479badWei Jia sizeof(kProfileLevels) / sizeof(kProfileLevels[0]); 214ab05b4ccb8ea59079d7f773aa0e090029c479badWei Jia if (index >= nProfileLevels) { 215180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return OMX_ErrorNoMore; 216180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 2175bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 218180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang profileLevel->eProfile = kProfileLevels[index].mProfile; 219180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang profileLevel->eLevel = kProfileLevels[index].mLevel; 220180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return OMX_ErrorNone; 221093024bfa271988655327e0fb761b581afa8bc11Robert Shih } 222180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 2235bc087c573c70c84c6a39946457590b42d392a33Andreas Huber default: 224093024bfa271988655327e0fb761b581afa8bc11Robert Shih return SimpleSoftOMXComponent::internalGetParameter(index, params); 2255bc087c573c70c84c6a39946457590b42d392a33Andreas Huber } 226093024bfa271988655327e0fb761b581afa8bc11Robert Shih} 227093024bfa271988655327e0fb761b581afa8bc11Robert Shih 2285bc087c573c70c84c6a39946457590b42d392a33Andreas HuberOMX_ERRORTYPE SoftAVC::internalSetParameter( 2295bc087c573c70c84c6a39946457590b42d392a33Andreas Huber OMX_INDEXTYPE index, const OMX_PTR params) { 230093024bfa271988655327e0fb761b581afa8bc11Robert Shih switch (index) { 231093024bfa271988655327e0fb761b581afa8bc11Robert Shih case OMX_IndexParamStandardComponentRole: 232093024bfa271988655327e0fb761b581afa8bc11Robert Shih { 233093024bfa271988655327e0fb761b581afa8bc11Robert Shih const OMX_PARAM_COMPONENTROLETYPE *roleParams = 234093024bfa271988655327e0fb761b581afa8bc11Robert Shih (const OMX_PARAM_COMPONENTROLETYPE *)params; 235093024bfa271988655327e0fb761b581afa8bc11Robert Shih 2365bc087c573c70c84c6a39946457590b42d392a33Andreas Huber if (strncmp((const char *)roleParams->cRole, 2375bc087c573c70c84c6a39946457590b42d392a33Andreas Huber "video_decoder.avc", 2385bc087c573c70c84c6a39946457590b42d392a33Andreas Huber OMX_MAX_STRINGNAME_SIZE - 1)) { 2395bc087c573c70c84c6a39946457590b42d392a33Andreas Huber return OMX_ErrorUndefined; 240180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 2415bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 2425bc087c573c70c84c6a39946457590b42d392a33Andreas Huber return OMX_ErrorNone; 2435bc087c573c70c84c6a39946457590b42d392a33Andreas Huber } 2445bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 2455bc087c573c70c84c6a39946457590b42d392a33Andreas Huber case OMX_IndexParamVideoPortFormat: 246180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang { 247180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = 248180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params; 249180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 2505bc087c573c70c84c6a39946457590b42d392a33Andreas Huber if (formatParams->nPortIndex > kOutputPortIndex) { 2515bc087c573c70c84c6a39946457590b42d392a33Andreas Huber return OMX_ErrorUndefined; 2525bc087c573c70c84c6a39946457590b42d392a33Andreas Huber } 2535bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 2545bc087c573c70c84c6a39946457590b42d392a33Andreas Huber if (formatParams->nIndex != 0) { 25587f2a558dd12043631e12c361abef301bf603140Andreas Huber return OMX_ErrorNoMore; 25687f2a558dd12043631e12c361abef301bf603140Andreas Huber } 25787f2a558dd12043631e12c361abef301bf603140Andreas Huber 25887f2a558dd12043631e12c361abef301bf603140Andreas Huber return OMX_ErrorNone; 25987f2a558dd12043631e12c361abef301bf603140Andreas Huber } 26087f2a558dd12043631e12c361abef301bf603140Andreas Huber 26187f2a558dd12043631e12c361abef301bf603140Andreas Huber default: 26287f2a558dd12043631e12c361abef301bf603140Andreas Huber return SimpleSoftOMXComponent::internalSetParameter(index, params); 26387f2a558dd12043631e12c361abef301bf603140Andreas Huber } 26487f2a558dd12043631e12c361abef301bf603140Andreas Huber} 26587f2a558dd12043631e12c361abef301bf603140Andreas Huber 2665bc087c573c70c84c6a39946457590b42d392a33Andreas HuberOMX_ERRORTYPE SoftAVC::getConfig( 2675bc087c573c70c84c6a39946457590b42d392a33Andreas Huber OMX_INDEXTYPE index, OMX_PTR params) { 268d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber switch (index) { 269d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber case OMX_IndexConfigCommonOutputCrop: 270d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber { 271d5e56231a598b180a1d898bb7dc61b75580e59a4Andreas Huber OMX_CONFIG_RECTTYPE *rectParams = (OMX_CONFIG_RECTTYPE *)params; 272180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 273180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (rectParams->nPortIndex != 1) { 274180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return OMX_ErrorUndefined; 275180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 276180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 277180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang rectParams->nLeft = mCropLeft; 278180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang rectParams->nTop = mCropTop; 279180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang rectParams->nWidth = mCropWidth; 280180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang rectParams->nHeight = mCropHeight; 281180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 282180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return OMX_ErrorNone; 283180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 284180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 285180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang default: 286180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return OMX_ErrorUnsupportedIndex; 287180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang } 288180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang} 289180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang 290180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhangvoid SoftAVC::onQueueFilled(OMX_U32 portIndex) { 291180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang if (mSignalledError || mOutputPortSettingsChange != NONE) { 292180d1b96ee2312f1056a58e26884a89d25ab62c8Chong Zhang return; 2935bc087c573c70c84c6a39946457590b42d392a33Andreas Huber } 2945bc087c573c70c84c6a39946457590b42d392a33Andreas Huber 295 if (mEOSStatus == OUTPUT_FRAMES_FLUSHED) { 296 return; 297 } 298 299 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex); 300 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex); 301 H264SwDecRet ret = H264SWDEC_PIC_RDY; 302 bool portSettingsChanged = false; 303 while ((mEOSStatus != INPUT_DATA_AVAILABLE || !inQueue.empty()) 304 && outQueue.size() == kNumOutputBuffers) { 305 306 if (mEOSStatus == INPUT_EOS_SEEN) { 307 drainAllOutputBuffers(); 308 return; 309 } 310 311 BufferInfo *inInfo = *inQueue.begin(); 312 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 313 ++mPicId; 314 315 OMX_BUFFERHEADERTYPE *header = new OMX_BUFFERHEADERTYPE; 316 memset(header, 0, sizeof(OMX_BUFFERHEADERTYPE)); 317 header->nTimeStamp = inHeader->nTimeStamp; 318 header->nFlags = inHeader->nFlags; 319 if (header->nFlags & OMX_BUFFERFLAG_EOS) { 320 mEOSStatus = INPUT_EOS_SEEN; 321 } 322 mPicToHeaderMap.add(mPicId, header); 323 inQueue.erase(inQueue.begin()); 324 325 H264SwDecInput inPicture; 326 H264SwDecOutput outPicture; 327 memset(&inPicture, 0, sizeof(inPicture)); 328 inPicture.dataLen = inHeader->nFilledLen; 329 inPicture.pStream = inHeader->pBuffer + inHeader->nOffset; 330 inPicture.picId = mPicId; 331 inPicture.intraConcealmentMethod = 1; 332 H264SwDecPicture decodedPicture; 333 334 while (inPicture.dataLen > 0) { 335 ret = H264SwDecDecode(mHandle, &inPicture, &outPicture); 336 if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY || 337 ret == H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY) { 338 inPicture.dataLen -= (u32)(outPicture.pStrmCurrPos - inPicture.pStream); 339 inPicture.pStream = outPicture.pStrmCurrPos; 340 if (ret == H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY) { 341 mHeadersDecoded = true; 342 H264SwDecInfo decoderInfo; 343 CHECK(H264SwDecGetInfo(mHandle, &decoderInfo) == H264SWDEC_OK); 344 345 if (handlePortSettingChangeEvent(&decoderInfo)) { 346 portSettingsChanged = true; 347 } 348 349 if (decoderInfo.croppingFlag && 350 handleCropRectEvent(&decoderInfo.cropParams)) { 351 portSettingsChanged = true; 352 } 353 } 354 } else { 355 if (portSettingsChanged) { 356 if (H264SwDecNextPicture(mHandle, &decodedPicture, 0) 357 == H264SWDEC_PIC_RDY) { 358 359 // Save this output buffer; otherwise, it will be 360 // lost during dynamic port reconfiguration because 361 // OpenMAX client will delete _all_ output buffers 362 // in the process. 363 saveFirstOutputBuffer( 364 decodedPicture.picId, 365 (uint8_t *)decodedPicture.pOutputPicture); 366 } 367 } 368 inPicture.dataLen = 0; 369 if (ret < 0) { 370 ALOGE("Decoder failed: %d", ret); 371 372 notify(OMX_EventError, OMX_ErrorUndefined, 373 ERROR_MALFORMED, NULL); 374 375 mSignalledError = true; 376 return; 377 } 378 } 379 } 380 inInfo->mOwnedByUs = false; 381 notifyEmptyBufferDone(inHeader); 382 383 if (portSettingsChanged) { 384 portSettingsChanged = false; 385 return; 386 } 387 388 if (mFirstPicture && !outQueue.empty()) { 389 drainOneOutputBuffer(mFirstPictureId, mFirstPicture); 390 delete[] mFirstPicture; 391 mFirstPicture = NULL; 392 mFirstPictureId = -1; 393 } 394 395 while (!outQueue.empty() && 396 mHeadersDecoded && 397 H264SwDecNextPicture(mHandle, &decodedPicture, 0) 398 == H264SWDEC_PIC_RDY) { 399 400 int32_t picId = decodedPicture.picId; 401 uint8_t *data = (uint8_t *) decodedPicture.pOutputPicture; 402 drainOneOutputBuffer(picId, data); 403 } 404 } 405} 406 407bool SoftAVC::handlePortSettingChangeEvent(const H264SwDecInfo *info) { 408 if (mWidth != info->picWidth || mHeight != info->picHeight) { 409 mWidth = info->picWidth; 410 mHeight = info->picHeight; 411 mPictureSize = mWidth * mHeight * 3 / 2; 412 mCropWidth = mWidth; 413 mCropHeight = mHeight; 414 updatePortDefinitions(); 415 notify(OMX_EventPortSettingsChanged, 1, 0, NULL); 416 mOutputPortSettingsChange = AWAITING_DISABLED; 417 return true; 418 } 419 420 return false; 421} 422 423bool SoftAVC::handleCropRectEvent(const CropParams *crop) { 424 if (mCropLeft != crop->cropLeftOffset || 425 mCropTop != crop->cropTopOffset || 426 mCropWidth != crop->cropOutWidth || 427 mCropHeight != crop->cropOutHeight) { 428 mCropLeft = crop->cropLeftOffset; 429 mCropTop = crop->cropTopOffset; 430 mCropWidth = crop->cropOutWidth; 431 mCropHeight = crop->cropOutHeight; 432 433 notify(OMX_EventPortSettingsChanged, 1, 434 OMX_IndexConfigCommonOutputCrop, NULL); 435 436 return true; 437 } 438 return false; 439} 440 441void SoftAVC::saveFirstOutputBuffer(int32_t picId, uint8_t *data) { 442 CHECK(mFirstPicture == NULL); 443 mFirstPictureId = picId; 444 445 mFirstPicture = new uint8_t[mPictureSize]; 446 memcpy(mFirstPicture, data, mPictureSize); 447} 448 449void SoftAVC::drainOneOutputBuffer(int32_t picId, uint8_t* data) { 450 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex); 451 BufferInfo *outInfo = *outQueue.begin(); 452 outQueue.erase(outQueue.begin()); 453 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 454 OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId); 455 outHeader->nTimeStamp = header->nTimeStamp; 456 outHeader->nFlags = header->nFlags; 457 outHeader->nFilledLen = mPictureSize; 458 memcpy(outHeader->pBuffer + outHeader->nOffset, 459 data, mPictureSize); 460 mPicToHeaderMap.removeItem(picId); 461 delete header; 462 outInfo->mOwnedByUs = false; 463 notifyFillBufferDone(outHeader); 464} 465 466bool SoftAVC::drainAllOutputBuffers() { 467 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex); 468 H264SwDecPicture decodedPicture; 469 470 while (!outQueue.empty()) { 471 BufferInfo *outInfo = *outQueue.begin(); 472 outQueue.erase(outQueue.begin()); 473 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 474 if (mHeadersDecoded && 475 H264SWDEC_PIC_RDY == 476 H264SwDecNextPicture(mHandle, &decodedPicture, 1 /* flush */)) { 477 478 int32_t picId = decodedPicture.picId; 479 CHECK(mPicToHeaderMap.indexOfKey(picId) >= 0); 480 481 memcpy(outHeader->pBuffer + outHeader->nOffset, 482 decodedPicture.pOutputPicture, 483 mPictureSize); 484 485 OMX_BUFFERHEADERTYPE *header = mPicToHeaderMap.valueFor(picId); 486 outHeader->nTimeStamp = header->nTimeStamp; 487 outHeader->nFlags = header->nFlags; 488 outHeader->nFilledLen = mPictureSize; 489 mPicToHeaderMap.removeItem(picId); 490 delete header; 491 } else { 492 outHeader->nTimeStamp = 0; 493 outHeader->nFilledLen = 0; 494 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 495 mEOSStatus = OUTPUT_FRAMES_FLUSHED; 496 } 497 498 outInfo->mOwnedByUs = false; 499 notifyFillBufferDone(outHeader); 500 } 501 502 return true; 503} 504 505void SoftAVC::onPortFlushCompleted(OMX_U32 portIndex) { 506 if (portIndex == kInputPortIndex) { 507 mEOSStatus = INPUT_DATA_AVAILABLE; 508 } 509} 510 511void SoftAVC::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { 512 switch (mOutputPortSettingsChange) { 513 case NONE: 514 break; 515 516 case AWAITING_DISABLED: 517 { 518 CHECK(!enabled); 519 mOutputPortSettingsChange = AWAITING_ENABLED; 520 break; 521 } 522 523 default: 524 { 525 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED); 526 CHECK(enabled); 527 mOutputPortSettingsChange = NONE; 528 break; 529 } 530 } 531} 532 533void SoftAVC::onReset() { 534 mSignalledError = false; 535 mOutputPortSettingsChange = NONE; 536} 537 538void SoftAVC::updatePortDefinitions() { 539 OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef; 540 def->format.video.nFrameWidth = mWidth; 541 def->format.video.nFrameHeight = mHeight; 542 def->format.video.nStride = def->format.video.nFrameWidth; 543 def->format.video.nSliceHeight = def->format.video.nFrameHeight; 544 545 def = &editPortInfo(1)->mDef; 546 def->format.video.nFrameWidth = mWidth; 547 def->format.video.nFrameHeight = mHeight; 548 def->format.video.nStride = def->format.video.nFrameWidth; 549 def->format.video.nSliceHeight = def->format.video.nFrameHeight; 550 551 def->nBufferSize = 552 (def->format.video.nFrameWidth 553 * def->format.video.nFrameHeight * 3) / 2; 554} 555 556} // namespace android 557 558android::SoftOMXComponent *createSoftOMXComponent( 559 const char *name, const OMX_CALLBACKTYPE *callbacks, 560 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 561 return new android::SoftAVC(name, callbacks, appData, component); 562} 563