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 3708e8227514f5ab99822dfae8b4d39414646ff59dVignesh Venkatasubramanian// Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies 3808e8227514f5ab99822dfae8b4d39414646ff59dVignesh Venkatasubramanian// mappings for up to 8 channels. This information is part of the Vorbis I 3908e8227514f5ab99822dfae8b4d39414646ff59dVignesh Venkatasubramanian// Specification: 4008e8227514f5ab99822dfae8b4d39414646ff59dVignesh Venkatasubramanian// http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html 4108e8227514f5ab99822dfae8b4d39414646ff59dVignesh Venkatasubramanianstatic const int kMaxChannels = 8; 4208e8227514f5ab99822dfae8b4d39414646ff59dVignesh Venkatasubramanian 43bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramaniantemplate<class T> 44bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic void InitOMXParams(T *params) { 45bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian params->nSize = sizeof(T); 46bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian params->nVersion.s.nVersionMajor = 1; 47bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian params->nVersion.s.nVersionMinor = 0; 48bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian params->nVersion.s.nRevision = 0; 49bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian params->nVersion.s.nStep = 0; 50bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 51bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 52bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh VenkatasubramanianSoftOpus::SoftOpus( 53bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const char *name, 54bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const OMX_CALLBACKTYPE *callbacks, 55bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_PTR appData, 56bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_COMPONENTTYPE **component) 57bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian : SimpleSoftOMXComponent(name, callbacks, appData, component), 58bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mInputBufferCount(0), 59bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mDecoder(NULL), 60bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mHeader(NULL), 61bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mCodecDelay(0), 62bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSeekPreRoll(0), 63bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mAnchorTimeUs(0), 64bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mNumFramesOutput(0), 65a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mHaveEOS(false), 66bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mOutputPortSettingsChange(NONE) { 67bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian initPorts(); 68bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian CHECK_EQ(initDecoder(), (status_t)OK); 69bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 70bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 71bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh VenkatasubramanianSoftOpus::~SoftOpus() { 72bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mDecoder != NULL) { 73bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opus_multistream_decoder_destroy(mDecoder); 74bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mDecoder = NULL; 75bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 76bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mHeader != NULL) { 77bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian delete mHeader; 78bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mHeader = NULL; 79bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 80bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 81bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 82bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianvoid SoftOpus::initPorts() { 83bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_PARAM_PORTDEFINITIONTYPE def; 84bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian InitOMXParams(&def); 85bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 86bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nPortIndex = 0; 87bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.eDir = OMX_DirInput; 88bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferCountMin = kNumBuffers; 89bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferCountActual = def.nBufferCountMin; 90bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferSize = 960 * 6; 91bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.bEnabled = OMX_TRUE; 92bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.bPopulated = OMX_FALSE; 93bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.eDomain = OMX_PortDomainAudio; 94bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.bBuffersContiguous = OMX_FALSE; 95bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferAlignment = 1; 96bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 97bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.cMIMEType = 98bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const_cast<char *>(MEDIA_MIMETYPE_AUDIO_OPUS); 99bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 100bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.pNativeRender = NULL; 101bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.bFlagErrorConcealment = OMX_FALSE; 10217d653523898c01816457743ab376a7b0427611fLajos Molnar def.format.audio.eEncoding = 10317d653523898c01816457743ab376a7b0427611fLajos Molnar (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS; 104bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 105bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian addPort(def); 106bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 107bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nPortIndex = 1; 108bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.eDir = OMX_DirOutput; 109bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferCountMin = kNumBuffers; 110bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferCountActual = def.nBufferCountMin; 11108e8227514f5ab99822dfae8b4d39414646ff59dVignesh Venkatasubramanian def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t) * kMaxChannels; 112bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.bEnabled = OMX_TRUE; 113bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.bPopulated = OMX_FALSE; 114bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.eDomain = OMX_PortDomainAudio; 115bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.bBuffersContiguous = OMX_FALSE; 116bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.nBufferAlignment = 2; 117bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 118bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.cMIMEType = const_cast<char *>("audio/raw"); 119bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.pNativeRender = NULL; 120bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.bFlagErrorConcealment = OMX_FALSE; 121bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 122bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 123bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian addPort(def); 124bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 125bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 126bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatus_t SoftOpus::initDecoder() { 127bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OK; 128bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 129bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 130bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh VenkatasubramanianOMX_ERRORTYPE SoftOpus::internalGetParameter( 131bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_INDEXTYPE index, OMX_PTR params) { 13217d653523898c01816457743ab376a7b0427611fLajos Molnar switch ((int)index) { 1331e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan case OMX_IndexParamAudioPortFormat: 1341e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan { 1351e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams = 1361e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params; 1371e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 1381e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan if (!isValidOMXParam(formatParams)) { 1391e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorBadParameter; 1401e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 1411e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 1421e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan if (formatParams->nPortIndex > 1) { 1431e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorUndefined; 1441e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 1451e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 1461e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan if (formatParams->nIndex > 0) { 1471e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorNoMore; 1481e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 1491e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 1501e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan formatParams->eEncoding = 1511e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan (formatParams->nPortIndex == 0) 1521e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan ? (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS : 1531e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan OMX_AUDIO_CodingPCM; 1541e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 1551e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorNone; 1561e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 1571e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 158bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian case OMX_IndexParamAudioAndroidOpus: 159bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian { 160bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams = 161bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian (OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params; 162bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 1632720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen if (!isValidOMXParam(opusParams)) { 1642720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen return OMX_ErrorBadParameter; 1652720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen } 1662720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen 167bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (opusParams->nPortIndex != 0) { 168bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorUndefined; 169bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 170bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 171bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opusParams->nAudioBandWidth = 0; 172bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opusParams->nSampleRate = kRate; 173bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opusParams->nBitRate = 0; 174bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 175bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (!isConfigured()) { 176bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opusParams->nChannels = 1; 177bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } else { 178bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opusParams->nChannels = mHeader->channels; 179bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 180bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 181bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorNone; 182bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 183bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 184bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian case OMX_IndexParamAudioPcm: 185bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian { 186bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 187bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 188bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 1892720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen if (!isValidOMXParam(pcmParams)) { 1902720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen return OMX_ErrorBadParameter; 1912720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen } 1922720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen 193bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (pcmParams->nPortIndex != 1) { 194bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorUndefined; 195bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 196bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 197bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->eNumData = OMX_NumericalDataSigned; 198bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->eEndian = OMX_EndianBig; 199bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->bInterleaved = OMX_TRUE; 200bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->nBitPerSample = 16; 201bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 202bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 203bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 204bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->nSamplingRate = kRate; 205bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 206bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (!isConfigured()) { 207bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->nChannels = 1; 208bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } else { 209bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian pcmParams->nChannels = mHeader->channels; 210bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 211bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 212bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorNone; 213bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 214bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 215bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian default: 216bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return SimpleSoftOMXComponent::internalGetParameter(index, params); 217bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 218bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 219bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 220bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh VenkatasubramanianOMX_ERRORTYPE SoftOpus::internalSetParameter( 221bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_INDEXTYPE index, const OMX_PTR params) { 22217d653523898c01816457743ab376a7b0427611fLajos Molnar switch ((int)index) { 223bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian case OMX_IndexParamStandardComponentRole: 224bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian { 225bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const OMX_PARAM_COMPONENTROLETYPE *roleParams = 226bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian (const OMX_PARAM_COMPONENTROLETYPE *)params; 227bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 2282720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen if (!isValidOMXParam(roleParams)) { 2292720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen return OMX_ErrorBadParameter; 2302720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen } 2312720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen 232bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (strncmp((const char *)roleParams->cRole, 233bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian "audio_decoder.opus", 234bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_MAX_STRINGNAME_SIZE - 1)) { 235bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorUndefined; 236bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 237bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 238bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorNone; 2391e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 2401e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 2411e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan case OMX_IndexParamAudioPortFormat: 2421e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan { 2431e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams = 2441e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params; 2451e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 2461e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan if (!isValidOMXParam(formatParams)) { 2471e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorBadParameter; 2481e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 2491e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 2501e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan if (formatParams->nPortIndex > 1) { 2511e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorUndefined; 2521e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 2531e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 2541e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan if ((formatParams->nPortIndex == 0 2551e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan && formatParams->eEncoding != 2561e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS) 2571e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan || (formatParams->nPortIndex == 1 2581e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) { 2591e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorUndefined; 2601e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan } 2611e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan 2621e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan return OMX_ErrorNone; 263bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 264bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 265bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian case OMX_IndexParamAudioAndroidOpus: 266bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian { 267bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *opusParams = 268bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian (const OMX_AUDIO_PARAM_ANDROID_OPUSTYPE *)params; 269bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 2702720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen if (!isValidOMXParam(opusParams)) { 2712720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen return OMX_ErrorBadParameter; 2722720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen } 2732720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen 274bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (opusParams->nPortIndex != 0) { 275bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorUndefined; 276bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 277bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 278bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return OMX_ErrorNone; 279bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 280bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 281bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian default: 282bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return SimpleSoftOMXComponent::internalSetParameter(index, params); 283bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 284bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 285bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 286bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianbool SoftOpus::isConfigured() const { 287bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return mInputBufferCount >= 1; 288bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 289bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 290bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic uint16_t ReadLE16(const uint8_t *data, size_t data_size, 291bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian uint32_t read_offset) { 292bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (read_offset + 1 > data_size) 293bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return 0; 294bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian uint16_t val; 295bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian val = data[read_offset]; 296bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian val |= data[read_offset + 1] << 8; 297bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return val; 298bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 299bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 300bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// Maximum packet size used in Xiph's opusdec. 301bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic const int kMaxOpusOutputPacketSizeSamples = 960 * 6; 302bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 303bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// Default audio output channel layout. Used to initialize |stream_map| in 304bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// OpusHeader, and passed to opus_multistream_decoder_create() when the header 305bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// does not contain mapping information. The values are valid only for mono and 306bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// stereo output: Opus streams with more than 2 channels require a stream map. 307bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic const int kMaxChannelsWithDefaultLayout = 2; 308bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic const uint8_t kDefaultOpusChannelLayout[kMaxChannelsWithDefaultLayout] = { 0, 1 }; 309bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 310bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// Parses Opus Header. Header spec: http://wiki.xiph.org/OggOpus#ID_Header 311bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic bool ParseOpusHeader(const uint8_t *data, size_t data_size, 312bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OpusHeader* header) { 313bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Size of the Opus header excluding optional mapping information. 31417d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderSize = 19; 315bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 316bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Offset to the channel count byte in the Opus header. 31717d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderChannelsOffset = 9; 318bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 319bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Offset to the pre-skip value in the Opus header. 32017d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderSkipSamplesOffset = 10; 321bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 322bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Offset to the gain value in the Opus header. 32317d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderGainOffset = 16; 324bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 325bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Offset to the channel mapping byte in the Opus header. 32617d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderChannelMappingOffset = 18; 327bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 328bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Opus Header contains a stream map. The mapping values are in the header 329bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // beyond the always present |kOpusHeaderSize| bytes of data. The mapping 330bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // data contains stream count, coupling information, and per channel mapping 331bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // values: 332bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // - Byte 0: Number of streams. 333bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // - Byte 1: Number coupled. 334bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // - Byte 2: Starting at byte 2 are |header->channels| uint8 mapping 335bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // values. 33617d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderNumStreamsOffset = kOpusHeaderSize; 33717d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderNumCoupledOffset = kOpusHeaderNumStreamsOffset + 1; 33817d653523898c01816457743ab376a7b0427611fLajos Molnar const size_t kOpusHeaderStreamMapOffset = kOpusHeaderNumStreamsOffset + 2; 339bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 340bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (data_size < kOpusHeaderSize) { 341bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGV("Header size is too small."); 342bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return false; 343bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 344bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->channels = *(data + kOpusHeaderChannelsOffset); 345bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 346bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (header->channels <= 0 || header->channels > kMaxChannels) { 347bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGV("Invalid Header, wrong channel count: %d", header->channels); 348bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return false; 349bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 350bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->skip_samples = ReadLE16(data, data_size, 351bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian kOpusHeaderSkipSamplesOffset); 352bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->gain_db = static_cast<int16_t>( 353bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ReadLE16(data, data_size, 354bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian kOpusHeaderGainOffset)); 355bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->channel_mapping = *(data + kOpusHeaderChannelMappingOffset); 356bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (!header->channel_mapping) { 357bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (header->channels > kMaxChannelsWithDefaultLayout) { 358bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGV("Invalid Header, missing stream map."); 359bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return false; 360bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 361bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->num_streams = 1; 362bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->num_coupled = header->channels > 1; 363bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->stream_map[0] = 0; 364bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->stream_map[1] = 1; 365bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return true; 366bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 367bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (data_size < kOpusHeaderStreamMapOffset + header->channels) { 368bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGV("Invalid stream map; insufficient data for current channel " 369bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian "count: %d", header->channels); 370bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return false; 371bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 372bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->num_streams = *(data + kOpusHeaderNumStreamsOffset); 373bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->num_coupled = *(data + kOpusHeaderNumCoupledOffset); 374bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (header->num_streams + header->num_coupled != header->channels) { 375bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGV("Inconsistent channel mapping."); 376bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return false; 377bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 378bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian for (int i = 0; i < header->channels; ++i) 379bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian header->stream_map[i] = *(data + kOpusHeaderStreamMapOffset + i); 380bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return true; 381bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 382bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 383bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian// Convert nanoseconds to number of samples. 384bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianstatic uint64_t ns_to_samples(uint64_t ns, int kRate) { 385bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return static_cast<double>(ns) * kRate / 1000000000; 386bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 387bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 388a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jiavoid SoftOpus::handleEOS() { 389a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia List<BufferInfo *> &inQueue = getPortQueue(0); 390a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia List<BufferInfo *> &outQueue = getPortQueue(1); 391a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia CHECK(!inQueue.empty() && !outQueue.empty()); 392a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia 393a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia BufferInfo *outInfo = *outQueue.begin(); 394a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 395a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia outHeader->nFilledLen = 0; 396a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia outHeader->nFlags = OMX_BUFFERFLAG_EOS; 397a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mHaveEOS = true; 398a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia 399a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia outQueue.erase(outQueue.begin()); 400a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia outInfo->mOwnedByUs = false; 401a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia notifyFillBufferDone(outHeader); 402a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia 403a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia BufferInfo *inInfo = *inQueue.begin(); 404a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 405a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia inQueue.erase(inQueue.begin()); 406a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia inInfo->mOwnedByUs = false; 407a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia notifyEmptyBufferDone(inHeader); 408a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia 409a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia ++mInputBufferCount; 410a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia} 411a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia 412a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jiavoid SoftOpus::onQueueFilled(OMX_U32 /* portIndex */) { 413bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian List<BufferInfo *> &inQueue = getPortQueue(0); 414bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian List<BufferInfo *> &outQueue = getPortQueue(1); 415bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 416bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mOutputPortSettingsChange != NONE) { 417bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 418bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 419bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 420a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia while (!mHaveEOS && !inQueue.empty() && !outQueue.empty()) { 421a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia BufferInfo *inInfo = *inQueue.begin(); 422a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 423bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 424a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia if (mInputBufferCount < 3) { 425a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia const uint8_t *data = inHeader->pBuffer + inHeader->nOffset; 426a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia size_t size = inHeader->nFilledLen; 427bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 428a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && size == 0) { 429a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia handleEOS(); 430bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 431bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 432bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 433a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia if (mInputBufferCount == 0) { 434a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia CHECK(mHeader == NULL); 435a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mHeader = new OpusHeader(); 436a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia memset(mHeader, 0, sizeof(*mHeader)); 437a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia if (!ParseOpusHeader(data, size, mHeader)) { 438a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia ALOGV("Parsing Opus Header failed."); 439a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 440a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia return; 441a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia } 442a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia 443a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia uint8_t channel_mapping[kMaxChannels] = {0}; 444a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia if (mHeader->channels <= kMaxChannelsWithDefaultLayout) { 445a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia memcpy(&channel_mapping, 446a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia kDefaultOpusChannelLayout, 447a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia kMaxChannelsWithDefaultLayout); 448a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia } else { 449a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia memcpy(&channel_mapping, 450a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mHeader->stream_map, 451a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mHeader->channels); 452a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia } 453a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia 454a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia int status = OPUS_INVALID_STATE; 455a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mDecoder = opus_multistream_decoder_create(kRate, 456a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mHeader->channels, 457a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mHeader->num_streams, 458a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mHeader->num_coupled, 459a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia channel_mapping, 460a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia &status); 461a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia if (!mDecoder || status != OPUS_OK) { 462a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia ALOGV("opus_multistream_decoder_create failed status=%s", 463a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia opus_strerror(status)); 464a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 465a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia return; 466a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia } 467a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia status = 468a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia opus_multistream_decoder_ctl(mDecoder, 469a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia OPUS_SET_GAIN(mHeader->gain_db)); 470a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia if (status != OPUS_OK) { 471a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia ALOGV("Failed to set OPUS header gain; status=%s", 472a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia opus_strerror(status)); 473a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 474a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia return; 475a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia } 476a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia } else if (mInputBufferCount == 1) { 477a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mCodecDelay = ns_to_samples( 478a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia *(reinterpret_cast<int64_t*>(inHeader->pBuffer + 479a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia inHeader->nOffset)), 480a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia kRate); 481a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mSamplesToDiscard = mCodecDelay; 4829b4b24a46f3f76ebb186df8bc01c58848af02108Vignesh Venkatasubramanian } else { 483a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mSeekPreRoll = ns_to_samples( 484a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia *(reinterpret_cast<int64_t*>(inHeader->pBuffer + 485a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia inHeader->nOffset)), 486a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia kRate); 487a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia notify(OMX_EventPortSettingsChanged, 1, 0, NULL); 488a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mOutputPortSettingsChange = AWAITING_DISABLED; 4899b4b24a46f3f76ebb186df8bc01c58848af02108Vignesh Venkatasubramanian } 490bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 491a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 492a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia handleEOS(); 493bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 494bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 495bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 496a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia inQueue.erase(inQueue.begin()); 497a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia inInfo->mOwnedByUs = false; 498a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia notifyEmptyBufferDone(inHeader); 499a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia ++mInputBufferCount; 500bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 501a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia continue; 502a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia } 503bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 5041b30bde3d4447e4c9b767c68584b8997bd930720Vignesh Venkatasubramanian // Ignore CSD re-submissions. 505a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia if (mInputBufferCount >= 3 && (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { 506a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 507a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia handleEOS(); 508a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia return; 509a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia } 510a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia 5111b30bde3d4447e4c9b767c68584b8997bd930720Vignesh Venkatasubramanian inQueue.erase(inQueue.begin()); 5121b30bde3d4447e4c9b767c68584b8997bd930720Vignesh Venkatasubramanian inInfo->mOwnedByUs = false; 5131b30bde3d4447e4c9b767c68584b8997bd930720Vignesh Venkatasubramanian notifyEmptyBufferDone(inHeader); 514a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia continue; 5151b30bde3d4447e4c9b767c68584b8997bd930720Vignesh Venkatasubramanian } 5161b30bde3d4447e4c9b767c68584b8997bd930720Vignesh Venkatasubramanian 517bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian BufferInfo *outInfo = *outQueue.begin(); 518bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 519bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 520199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) { 521a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia handleEOS(); 522bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 523bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 524bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 525bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (inHeader->nOffset == 0) { 526bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mAnchorTimeUs = inHeader->nTimeStamp; 527bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mNumFramesOutput = 0; 528bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 529bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 530bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // When seeking to zero, |mCodecDelay| samples has to be discarded 531bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // instead of |mSeekPreRoll| samples (as we would when seeking to any 532bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // other timestamp). 533bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (inHeader->nTimeStamp == 0) { 534bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSamplesToDiscard = mCodecDelay; 535bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 536bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 537bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const uint8_t *data = inHeader->pBuffer + inHeader->nOffset; 538bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const uint32_t size = inHeader->nFilledLen; 539e6a2b5d7d2e9fa8db10ccb911d472c0fefa77557Wonsik Kim size_t frameSize = kMaxOpusOutputPacketSizeSamples; 540e6a2b5d7d2e9fa8db10ccb911d472c0fefa77557Wonsik Kim if (frameSize > outHeader->nAllocLen / sizeof(int16_t) / mHeader->channels) { 541e6a2b5d7d2e9fa8db10ccb911d472c0fefa77557Wonsik Kim frameSize = outHeader->nAllocLen / sizeof(int16_t) / mHeader->channels; 542ff64ea33382081f46d4b1061df00298bbbe3dd65Wonsik Kim android_errorWriteLog(0x534e4554, "27833616"); 543e6a2b5d7d2e9fa8db10ccb911d472c0fefa77557Wonsik Kim } 544bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 545bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian int numFrames = opus_multistream_decode(mDecoder, 546bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian data, 547bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian size, 548bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian (int16_t *)outHeader->pBuffer, 549e6a2b5d7d2e9fa8db10ccb911d472c0fefa77557Wonsik Kim frameSize, 550bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 0); 551bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (numFrames < 0) { 552bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian ALOGE("opus_multistream_decode returned %d", numFrames); 553bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 554bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 555bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 556bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 557bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outHeader->nOffset = 0; 558bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mSamplesToDiscard > 0) { 559bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mSamplesToDiscard > numFrames) { 560bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSamplesToDiscard -= numFrames; 561bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian numFrames = 0; 562bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } else { 563bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian numFrames -= mSamplesToDiscard; 564bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outHeader->nOffset = mSamplesToDiscard * sizeof(int16_t) * 565bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mHeader->channels; 566bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSamplesToDiscard = 0; 567bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 568bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 569bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 570bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outHeader->nFilledLen = numFrames * sizeof(int16_t) * mHeader->channels; 571bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 572bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outHeader->nTimeStamp = mAnchorTimeUs + 573bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian (mNumFramesOutput * 1000000ll) / 574bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian kRate; 575bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 576bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mNumFramesOutput += numFrames; 577bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 578199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 579a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia outHeader->nFlags = OMX_BUFFERFLAG_EOS; 580a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mHaveEOS = true; 581199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia } else { 582a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia outHeader->nFlags = 0; 583199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia } 584bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 585a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia inInfo->mOwnedByUs = false; 586a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia inQueue.erase(inQueue.begin()); 587a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia notifyEmptyBufferDone(inHeader); 588a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia ++mInputBufferCount; 589a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia 590bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outInfo->mOwnedByUs = false; 591bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian outQueue.erase(outQueue.begin()); 592bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian notifyFillBufferDone(outHeader); 593bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 594bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 595bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 596bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianvoid SoftOpus::onPortFlushCompleted(OMX_U32 portIndex) { 597bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (portIndex == 0 && mDecoder != NULL) { 598bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // Make sure that the next buffer output does not still 599bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian // depend on fragments from the last one decoded. 600bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mNumFramesOutput = 0; 601bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opus_multistream_decoder_ctl(mDecoder, OPUS_RESET_STATE); 602bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mAnchorTimeUs = 0; 603bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mSamplesToDiscard = mSeekPreRoll; 604a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mHaveEOS = false; 605bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 606bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 607bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 608bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianvoid SoftOpus::onReset() { 609bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mInputBufferCount = 0; 610bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mNumFramesOutput = 0; 611bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mDecoder != NULL) { 612bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian opus_multistream_decoder_destroy(mDecoder); 613bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mDecoder = NULL; 614bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 615bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (mHeader != NULL) { 616bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian delete mHeader; 617bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mHeader = NULL; 618bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 619bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 620bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mOutputPortSettingsChange = NONE; 621a8ca1d1697427123148a28c33e26fe1ad2b9d948Wei Jia mHaveEOS = false; 622bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 623bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 624bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianvoid SoftOpus::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { 625bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian if (portIndex != 1) { 626bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return; 627bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 628bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 629bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian switch (mOutputPortSettingsChange) { 630bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian case NONE: 631bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian break; 632bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 633bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian case AWAITING_DISABLED: 634bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian { 635bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian CHECK(!enabled); 636bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mOutputPortSettingsChange = AWAITING_ENABLED; 637bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian break; 638bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 639bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 640bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian default: 641bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian { 642bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED); 643bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian CHECK(enabled); 644bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian mOutputPortSettingsChange = NONE; 645bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian break; 646bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 647bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian } 648bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 649bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 650bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} // namespace android 651bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian 652bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanianandroid::SoftOMXComponent *createSoftOMXComponent( 653bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian const char *name, const OMX_CALLBACKTYPE *callbacks, 654bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian OMX_PTR appData, OMX_COMPONENTTYPE **component) { 655bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian return new android::SoftOpus(name, callbacks, appData, component); 656bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian} 657