1bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian/* 2bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian * Copyright (C) 2014 The Android Open Source Project 3bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian * 4bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian * Licensed under the Apache License, Version 2.0 (the "License"); 5bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian * you may not use this file except in compliance with the License. 6bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian * You may obtain a copy of the License at 7bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian * 8bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian * http://www.apache.org/licenses/LICENSE-2.0 9bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian * 10bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian * Unless required by applicable law or agreed to in writing, software 11bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian * distributed under the License is distributed on an "AS IS" BASIS, 12bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian * See the License for the specific language governing permissions and 14bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian * limitations under the License. 15bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian */ 16bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 17bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian//#define LOG_NDEBUG 0 18bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian#define LOG_TAG "SoftOpus" 19bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian#include <utils/Log.h> 20bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 21bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian#include "SoftOpus.h" 2217d653523898c01816457743ab376a7b0427611fLajos Molnar#include <OMX_AudioExt.h> 2317d653523898c01816457743ab376a7b0427611fLajos Molnar#include <OMX_IndexExt.h> 24bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 25bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian#include <media/stagefright/foundation/ADebug.h> 26bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian#include <media/stagefright/MediaDefs.h> 27bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 28bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianextern "C" { 29bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian #include <opus.h> 30bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian #include <opus_multistream.h> 31bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 32bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 33bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramaniannamespace android { 34bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 35bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic const int kRate = 48000; 36bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 37bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramaniantemplate<class T> 38bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic void InitOMXParams(T *params) { 39bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian params->nSize = sizeof(T); 40bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian params->nVersion.s.nVersionMajor = 1; 41bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian params->nVersion.s.nVersionMinor = 0; 42bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian params->nVersion.s.nRevision = 0; 43bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian params->nVersion.s.nStep = 0; 44bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 45bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 46bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh VenkatasubramanianSoftOpus::SoftOpus( 47bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const char *name, 48bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const OMX_CALLBACKTYPE *callbacks, 49bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_PTR appData, 50bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_COMPONENTTYPE **component) 51bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian : SimpleSoftOMXComponent(name, callbacks, appData, component), 52bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mInputBufferCount(0), 53bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mDecoder(NULL), 54bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mHeader(NULL), 55bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mCodecDelay(0), 56bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSeekPreRoll(0), 57bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mAnchorTimeUs(0), 58bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mNumFramesOutput(0), 59bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mOutputPortSettingsChange(NONE) { 60bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian initPorts(); 61bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian CHECK_EQ(initDecoder(), (status_t)OK); 62bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 63bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 64bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh VenkatasubramanianSoftOpus::~SoftOpus() { 65bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mDecoder != NULL) { 66bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opus_multistream_decoder_destroy(mDecoder); 67bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mDecoder = NULL; 68bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 69bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mHeader != NULL) { 70bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian delete mHeader; 71bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mHeader = NULL; 72bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 73bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 74bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 75bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianvoid SoftOpus::initPorts() { 76bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_PARAM_PORTDEFINITIONTYPE def; 77bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian InitOMXParams(&def); 78bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 79bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nPortIndex = 0; 80bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.eDir = OMX_DirInput; 81bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferCountMin = kNumBuffers; 82bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferCountActual = def.nBufferCountMin; 83bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferSize = 960 * 6; 84bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.bEnabled = OMX_TRUE; 85bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.bPopulated = OMX_FALSE; 86bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.eDomain = OMX_PortDomainAudio; 87bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.bBuffersContiguous = OMX_FALSE; 88bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferAlignment = 1; 89bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 90bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.cMIMEType = 91bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const_cast<char *>(MEDIA_MIMETYPE_AUDIO_OPUS); 92bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 93bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.pNativeRender = NULL; 94bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.bFlagErrorConcealment = OMX_FALSE; 9517d653523898c01816457743ab376a7b0427611fLajos Molnar def.format.audio.eEncoding = 9617d653523898c01816457743ab376a7b0427611fLajos Molnar (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS; 97bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 98bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian addPort(def); 99bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 100bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nPortIndex = 1; 101bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.eDir = OMX_DirOutput; 102bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferCountMin = kNumBuffers; 103bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferCountActual = def.nBufferCountMin; 104bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t); 105bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.bEnabled = OMX_TRUE; 106bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.bPopulated = OMX_FALSE; 107bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.eDomain = OMX_PortDomainAudio; 108bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.bBuffersContiguous = OMX_FALSE; 109bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferAlignment = 2; 110bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 111bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.cMIMEType = const_cast<char *>("audio/raw"); 112bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.pNativeRender = NULL; 113bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.bFlagErrorConcealment = OMX_FALSE; 114bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 115bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 116bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian addPort(def); 117bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 118bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 119bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatus_t SoftOpus::initDecoder() { 120bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OK; 121bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 122bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 123bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh VenkatasubramanianOMX_ERRORTYPE SoftOpus::internalGetParameter( 124bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_INDEXTYPE index, OMX_PTR params) { 12517d653523898c01816457743ab376a7b0427611fLajos Molnar switch ((int)index) { 126bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian case OMX_IndexParamAudioAndroidOpus: 127bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian { 128bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams = 129bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian (OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params; 130bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 131bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (opusParams->nPortIndex != 0) { 132bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorUndefined; 133bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 134bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 135bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opusParams->nAudioBandWidth = 0; 136bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opusParams->nSampleRate = kRate; 137bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opusParams->nBitRate = 0; 138bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 139bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (!isConfigured()) { 140bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opusParams->nChannels = 1; 141bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } else { 142bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opusParams->nChannels = mHeader->channels; 143bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 144bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 145bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorNone; 146bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 147bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 148bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian case OMX_IndexParamAudioPcm: 149bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian { 150bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 151bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 152bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 153bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (pcmParams->nPortIndex != 1) { 154bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorUndefined; 155bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 156bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 157bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->eNumData = OMX_NumericalDataSigned; 158bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->eEndian = OMX_EndianBig; 159bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->bInterleaved = OMX_TRUE; 160bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->nBitPerSample = 16; 161bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 162bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 163bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 164bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->nSamplingRate = kRate; 165bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 166bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (!isConfigured()) { 167bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->nChannels = 1; 168bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } else { 169bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->nChannels = mHeader->channels; 170bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 171bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 172bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorNone; 173bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 174bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 175bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian default: 176bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return SimpleSoftOMXComponent::internalGetParameter(index, params); 177bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 178bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 179bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 180bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh VenkatasubramanianOMX_ERRORTYPE SoftOpus::internalSetParameter( 181bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_INDEXTYPE index, const OMX_PTR params) { 18217d653523898c01816457743ab376a7b0427611fLajos Molnar switch ((int)index) { 183bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian case OMX_IndexParamStandardComponentRole: 184bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian { 185bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const OMX_PARAM_COMPONENTROLETYPE *roleParams = 186bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian (const OMX_PARAM_COMPONENTROLETYPE *)params; 187bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 188bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (strncmp((const char *)roleParams->cRole, 189bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian "audio_decoder.opus", 190bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_MAX_STRINGNAME_SIZE - 1)) { 191bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorUndefined; 192bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 193bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 194bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorNone; 195bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 196bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 197bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian case OMX_IndexParamAudioAndroidOpus: 198bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian { 199bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams = 200bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian (const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params; 201bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 202bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (opusParams->nPortIndex != 0) { 203bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorUndefined; 204bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 205bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 206bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorNone; 207bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 208bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 209bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian default: 210bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return SimpleSoftOMXComponent::internalSetParameter(index, params); 211bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 212bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 213bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 214bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianbool SoftOpus::isConfigured() const { 215bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return mInputBufferCount >= 1; 216bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 217bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 218bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic uint16_t ReadLE16(const uint8_t *data, size_t data_size, 219bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian uint32_t read_offset) { 220bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (read_offset + 1 > data_size) 221bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return 0; 222bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian uint16_t val; 223bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian val = data[read_offset]; 224bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian val |= data[read_offset + 1] << 8; 225bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return val; 226bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 227bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 228bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies 229bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// mappings for up to 8 channels. This information is part of the Vorbis I 230bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// Specification: 231bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html 232bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic const int kMaxChannels = 8; 233bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 234bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// Maximum packet size used in Xiph's opusdec. 235bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic const int kMaxOpusOutputPacketSizeSamples = 960 * 6; 236bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 237bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// Default audio output channel layout. Used to initialize |stream_map| in 238bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// OpusHeader, and passed to opus_multistream_decoder_create() when the header 239bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// does not contain mapping information. The values are valid only for mono and 240bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// stereo output: Opus streams with more than 2 channels require a stream map. 241bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic const int kMaxChannelsWithDefaultLayout = 2; 242bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic const uint8_t kDefaultOpusChannelLayout[kMaxChannelsWithDefaultLayout] = { 0, 1 }; 243bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 244bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// Parses Opus Header. Header spec: http://wiki.xiph.org/OggOpus#ID_Header 245bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic bool ParseOpusHeader(const uint8_t *data, size_t data_size, 246bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OpusHeader* header) { 247bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Size of the Opus header excluding optional mapping information. 24817d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderSize = 19; 249bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 250bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Offset to the channel count byte in the Opus header. 25117d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderChannelsOffset = 9; 252bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 253bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Offset to the pre-skip value in the Opus header. 25417d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderSkipSamplesOffset = 10; 255bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 256bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Offset to the gain value in the Opus header. 25717d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderGainOffset = 16; 258bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 259bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Offset to the channel mapping byte in the Opus header. 26017d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderChannelMappingOffset = 18; 261bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 262bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Opus Header contains a stream map. The mapping values are in the header 263bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // beyond the always present |kOpusHeaderSize| bytes of data. The mapping 264bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // data contains stream count, coupling information, and per channel mapping 265bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // values: 266bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // - Byte 0: Number of streams. 267bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // - Byte 1: Number coupled. 268bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // - Byte 2: Starting at byte 2 are |header->channels| uint8 mapping 269bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // values. 27017d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderNumStreamsOffset = kOpusHeaderSize; 27117d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderNumCoupledOffset = kOpusHeaderNumStreamsOffset + 1; 27217d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderStreamMapOffset = kOpusHeaderNumStreamsOffset + 2; 273bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 274bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (data_size < kOpusHeaderSize) { 275bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGV("Header size is too small."); 276bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return false; 277bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 278bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->channels = *(data + kOpusHeaderChannelsOffset); 279bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 280bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (header->channels <= 0 || header->channels > kMaxChannels) { 281bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGV("Invalid Header, wrong channel count: %d", header->channels); 282bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return false; 283bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 284bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->skip_samples = ReadLE16(data, data_size, 285bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian kOpusHeaderSkipSamplesOffset); 286bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->gain_db = static_cast<int16_t>( 287bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ReadLE16(data, data_size, 288bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian kOpusHeaderGainOffset)); 289bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->channel_mapping = *(data + kOpusHeaderChannelMappingOffset); 290bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (!header->channel_mapping) { 291bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (header->channels > kMaxChannelsWithDefaultLayout) { 292bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGV("Invalid Header, missing stream map."); 293bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return false; 294bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 295bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->num_streams = 1; 296bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->num_coupled = header->channels > 1; 297bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->stream_map[0] = 0; 298bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->stream_map[1] = 1; 299bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return true; 300bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 301bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (data_size < kOpusHeaderStreamMapOffset + header->channels) { 302bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGV("Invalid stream map; insufficient data for current channel " 303bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian "count: %d", header->channels); 304bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return false; 305bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 306bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->num_streams = *(data + kOpusHeaderNumStreamsOffset); 307bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->num_coupled = *(data + kOpusHeaderNumCoupledOffset); 308bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (header->num_streams + header->num_coupled != header->channels) { 309bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGV("Inconsistent channel mapping."); 310bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return false; 311bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 312bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian for (int i = 0; i < header->channels; ++i) 313bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->stream_map[i] = *(data + kOpusHeaderStreamMapOffset + i); 314bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return true; 315bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 316bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 317bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// Convert nanoseconds to number of samples. 318bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic uint64_t ns_to_samples(uint64_t ns, int kRate) { 319bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return static_cast<double>(ns) * kRate / 1000000000; 320bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 321bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 322bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianvoid SoftOpus::onQueueFilled(OMX_U32 portIndex) { 323bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian List<BufferInfo *> &inQueue = getPortQueue(0); 324bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian List<BufferInfo *> &outQueue = getPortQueue(1); 325bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 326bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mOutputPortSettingsChange != NONE) { 327bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 328bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 329bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 330bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (portIndex == 0 && mInputBufferCount < 3) { 331bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian BufferInfo *info = *inQueue.begin(); 332bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_BUFFERHEADERTYPE *header = info->mHeader; 333bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 334bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const uint8_t *data = header->pBuffer + header->nOffset; 335bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian size_t size = header->nFilledLen; 336bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 337bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mInputBufferCount == 0) { 338bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian CHECK(mHeader == NULL); 339bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mHeader = new OpusHeader(); 340bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian memset(mHeader, 0, sizeof(*mHeader)); 341bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (!ParseOpusHeader(data, size, mHeader)) { 342bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGV("Parsing Opus Header failed."); 343bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 344bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 345bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 346bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 347bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian uint8_t channel_mapping[kMaxChannels] = {0}; 348bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian memcpy(&channel_mapping, 349bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian kDefaultOpusChannelLayout, 350bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian kMaxChannelsWithDefaultLayout); 351bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 352bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian int status = OPUS_INVALID_STATE; 353bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mDecoder = opus_multistream_decoder_create(kRate, 354bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mHeader->channels, 355bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mHeader->num_streams, 356bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mHeader->num_coupled, 357bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian channel_mapping, 358bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian &status); 359bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (!mDecoder || status != OPUS_OK) { 360bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGV("opus_multistream_decoder_create failed status=%s", 361bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opus_strerror(status)); 362bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 363bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 364bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 365bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian status = 366bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opus_multistream_decoder_ctl(mDecoder, 367bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OPUS_SET_GAIN(mHeader->gain_db)); 368bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (status != OPUS_OK) { 369bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGV("Failed to set OPUS header gain; status=%s", 370bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opus_strerror(status)); 371bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 372bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 373bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 374bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } else if (mInputBufferCount == 1) { 375bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mCodecDelay = ns_to_samples( 376bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian *(reinterpret_cast<int64_t*>(header->pBuffer + 377bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->nOffset)), 378bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian kRate); 379bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSamplesToDiscard = mCodecDelay; 380bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } else { 381bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSeekPreRoll = ns_to_samples( 382bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian *(reinterpret_cast<int64_t*>(header->pBuffer + 383bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->nOffset)), 384bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian kRate); 385bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian notify(OMX_EventPortSettingsChanged, 1, 0, NULL); 386bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mOutputPortSettingsChange = AWAITING_DISABLED; 387bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 388bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 389bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian inQueue.erase(inQueue.begin()); 390bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian info->mOwnedByUs = false; 391bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian notifyEmptyBufferDone(header); 392bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ++mInputBufferCount; 393bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 394bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 395bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 396bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian while (!inQueue.empty() && !outQueue.empty()) { 397bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian BufferInfo *inInfo = *inQueue.begin(); 398bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 399bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 400bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian BufferInfo *outInfo = *outQueue.begin(); 401bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 402bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 403bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 404bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian inQueue.erase(inQueue.begin()); 405bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian inInfo->mOwnedByUs = false; 406bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian notifyEmptyBufferDone(inHeader); 407bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 408bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outHeader->nFilledLen = 0; 409bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outHeader->nFlags = OMX_BUFFERFLAG_EOS; 410bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 411bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outQueue.erase(outQueue.begin()); 412bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outInfo->mOwnedByUs = false; 413bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian notifyFillBufferDone(outHeader); 414bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 415bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 416bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 417bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (inHeader->nOffset == 0) { 418bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mAnchorTimeUs = inHeader->nTimeStamp; 419bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mNumFramesOutput = 0; 420bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 421bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 422bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // When seeking to zero, |mCodecDelay| samples has to be discarded 423bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // instead of |mSeekPreRoll| samples (as we would when seeking to any 424bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // other timestamp). 425bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (inHeader->nTimeStamp == 0) { 426bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSamplesToDiscard = mCodecDelay; 427bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 428bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 429bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const uint8_t *data = inHeader->pBuffer + inHeader->nOffset; 430bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const uint32_t size = inHeader->nFilledLen; 431bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 432bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian int numFrames = opus_multistream_decode(mDecoder, 433bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian data, 434bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian size, 435bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian (int16_t *)outHeader->pBuffer, 436bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian kMaxOpusOutputPacketSizeSamples, 437bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 0); 438bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (numFrames < 0) { 439bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGE("opus_multistream_decode returned %d", numFrames); 440bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 441bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 442bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 443bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 444bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outHeader->nOffset = 0; 445bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mSamplesToDiscard > 0) { 446bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mSamplesToDiscard > numFrames) { 447bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSamplesToDiscard -= numFrames; 448bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian numFrames = 0; 449bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } else { 450bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian numFrames -= mSamplesToDiscard; 451bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outHeader->nOffset = mSamplesToDiscard * sizeof(int16_t) * 452bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mHeader->channels; 453bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSamplesToDiscard = 0; 454bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 455bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 456bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 457bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels; 458bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outHeader->nFlags = 0; 459bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 460bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outHeader->nTimeStamp = mAnchorTimeUs + 461bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian (mNumFramesOutput * 1000000ll) / 462bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian kRate; 463bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 464bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mNumFramesOutput += numFrames; 465bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 466bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian inInfo->mOwnedByUs = false; 467bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian inQueue.erase(inQueue.begin()); 468bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian inInfo = NULL; 469bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian notifyEmptyBufferDone(inHeader); 470bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian inHeader = NULL; 471bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 472bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outInfo->mOwnedByUs = false; 473bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outQueue.erase(outQueue.begin()); 474bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outInfo = NULL; 475bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian notifyFillBufferDone(outHeader); 476bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outHeader = NULL; 477bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 478bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ++mInputBufferCount; 479bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 480bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 481bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 482bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianvoid SoftOpus::onPortFlushCompleted(OMX_U32 portIndex) { 483bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (portIndex == 0 && mDecoder != NULL) { 484bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Make sure that the next buffer output does not still 485bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // depend on fragments from the last one decoded. 486bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mNumFramesOutput = 0; 487bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE); 488bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mAnchorTimeUs = 0; 489bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSamplesToDiscard = mSeekPreRoll; 490bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 491bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 492bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 493bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianvoid SoftOpus::onReset() { 494bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mInputBufferCount = 0; 495bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mNumFramesOutput = 0; 496bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mDecoder != NULL) { 497bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opus_multistream_decoder_destroy(mDecoder); 498bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mDecoder = NULL; 499bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 500bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mHeader != NULL) { 501bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian delete mHeader; 502bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mHeader = NULL; 503bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 504bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 505bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mOutputPortSettingsChange = NONE; 506bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 507bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 508bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianvoid SoftOpus::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { 509bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (portIndex != 1) { 510bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 511bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 512bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 513bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian switch (mOutputPortSettingsChange) { 514bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian case NONE: 515bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian break; 516bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 517bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian case AWAITING_DISABLED: 518bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian { 519bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian CHECK(!enabled); 520bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mOutputPortSettingsChange = AWAITING_ENABLED; 521bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian break; 522bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 523bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 524bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian default: 525bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian { 526bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED); 527bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian CHECK(enabled); 528bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mOutputPortSettingsChange = NONE; 529bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian break; 530bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 531bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 532bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 533bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 534bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} // namespace android 535bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 536bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianandroid::SoftOMXComponent *createSoftOMXComponent( 537bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const char *name, const OMX_CALLBACKTYPE *callbacks, 538bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_PTR appData, OMX_COMPONENTTYPE **component) { 539bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return new android::SoftOpus(name, callbacks, appData, component); 540bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 541