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