1bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber/*
2bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Copyright (C) 2011 The Android Open Source Project
3bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber *
4bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * you may not use this file except in compliance with the License.
6bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * You may obtain a copy of the License at
7bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber *
8bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber *
10bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Unless required by applicable law or agreed to in writing, software
11bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * See the License for the specific language governing permissions and
14bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * limitations under the License.
15bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber */
16bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
17bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber//#define LOG_NDEBUG 0
18bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#define LOG_TAG "SoftVorbis"
19bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <utils/Log.h>
20bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
21bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include "SoftVorbis.h"
22bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
23bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <media/stagefright/foundation/ADebug.h>
24bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <media/stagefright/MediaDefs.h>
25bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
26bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberextern "C" {
27bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    #include <Tremolo/codec_internal.h>
28bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
29bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
30bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
31bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
32bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
33bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
34bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubernamespace android {
35bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
36bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubertemplate<class T>
37bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberstatic void InitOMXParams(T *params) {
38bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nSize = sizeof(T);
39bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nVersion.s.nVersionMajor = 1;
40bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nVersion.s.nVersionMinor = 0;
41bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nVersion.s.nRevision = 0;
42bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nVersion.s.nStep = 0;
43bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
44bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
45bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberSoftVorbis::SoftVorbis(
46bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const char *name,
47bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const OMX_CALLBACKTYPE *callbacks,
48bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_PTR appData,
49bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_COMPONENTTYPE **component)
50bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    : SimpleSoftOMXComponent(name, callbacks, appData, component),
51bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mInputBufferCount(0),
52bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mState(NULL),
53bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mVi(NULL),
54bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mAnchorTimeUs(0),
55bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mNumFramesOutput(0),
56bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mNumFramesLeftOnPage(-1),
57bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mOutputPortSettingsChange(NONE) {
58bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    initPorts();
59bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    CHECK_EQ(initDecoder(), (status_t)OK);
60bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
61bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
62bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberSoftVorbis::~SoftVorbis() {
63bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (mState != NULL) {
64bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        vorbis_dsp_clear(mState);
65bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        delete mState;
66bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mState = NULL;
67bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
68bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
69bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (mVi != NULL) {
70bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        vorbis_info_clear(mVi);
71bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        delete mVi;
72bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mVi = NULL;
73bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
74bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
75bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
76bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftVorbis::initPorts() {
77bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    OMX_PARAM_PORTDEFINITIONTYPE def;
78bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    InitOMXParams(&def);
79bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
80bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nPortIndex = 0;
81bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.eDir = OMX_DirInput;
82bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferCountMin = kNumBuffers;
83bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferCountActual = def.nBufferCountMin;
84bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferSize = 8192;
85bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bEnabled = OMX_TRUE;
86bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bPopulated = OMX_FALSE;
87bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.eDomain = OMX_PortDomainAudio;
88bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bBuffersContiguous = OMX_FALSE;
89bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferAlignment = 1;
90bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
91bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.cMIMEType =
92bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const_cast<char *>(MEDIA_MIMETYPE_AUDIO_VORBIS);
93bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
94bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.pNativeRender = NULL;
95bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
96bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
97bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
98bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    addPort(def);
99bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
100bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nPortIndex = 1;
101bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.eDir = OMX_DirOutput;
102bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferCountMin = kNumBuffers;
103bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferCountActual = def.nBufferCountMin;
104bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t);
105bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bEnabled = OMX_TRUE;
106bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bPopulated = OMX_FALSE;
107bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.eDomain = OMX_PortDomainAudio;
108bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bBuffersContiguous = OMX_FALSE;
109bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferAlignment = 2;
110bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
111bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
112bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.pNativeRender = NULL;
113bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
114bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
115bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
116bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    addPort(def);
117bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
118bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
119bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberstatus_t SoftVorbis::initDecoder() {
120bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    return OK;
121bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
122bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
123bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberOMX_ERRORTYPE SoftVorbis::internalGetParameter(
124bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_INDEXTYPE index, OMX_PTR params) {
125bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    switch (index) {
126bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case OMX_IndexParamAudioVorbis:
127bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
128bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            OMX_AUDIO_PARAM_VORBISTYPE *vorbisParams =
129bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                (OMX_AUDIO_PARAM_VORBISTYPE *)params;
130bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
131bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (vorbisParams->nPortIndex != 0) {
132bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return OMX_ErrorUndefined;
133bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
134bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
135bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            vorbisParams->nBitRate = 0;
136bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            vorbisParams->nMinBitRate = 0;
137bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            vorbisParams->nMaxBitRate = 0;
138bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            vorbisParams->nAudioBandWidth = 0;
139bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            vorbisParams->nQuality = 3;
140bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            vorbisParams->bManaged = OMX_FALSE;
141bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            vorbisParams->bDownmix = OMX_FALSE;
142bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
143bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (!isConfigured()) {
144bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                vorbisParams->nChannels = 1;
145bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                vorbisParams->nSampleRate = 44100;
146bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            } else {
147bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                vorbisParams->nChannels = mVi->channels;
148bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                vorbisParams->nSampleRate = mVi->rate;
149bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                vorbisParams->nBitRate = mVi->bitrate_nominal;
150bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                vorbisParams->nMinBitRate = mVi->bitrate_lower;
151bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                vorbisParams->nMaxBitRate = mVi->bitrate_upper;
152bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
153bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
154bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return OMX_ErrorNone;
155bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
156bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
157bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case OMX_IndexParamAudioPcm:
158bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
159bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
160bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
161bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
162bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (pcmParams->nPortIndex != 1) {
163bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return OMX_ErrorUndefined;
164bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
165bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
166bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->eNumData = OMX_NumericalDataSigned;
167bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->eEndian = OMX_EndianBig;
168bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->bInterleaved = OMX_TRUE;
169bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->nBitPerSample = 16;
170bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
171bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
172bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
173bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
174bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (!isConfigured()) {
175bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                pcmParams->nChannels = 1;
176bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                pcmParams->nSamplingRate = 44100;
177bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            } else {
178bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                pcmParams->nChannels = mVi->channels;
179bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                pcmParams->nSamplingRate = mVi->rate;
180bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
181bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
182bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return OMX_ErrorNone;
183bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
184bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
185bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        default:
186bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return SimpleSoftOMXComponent::internalGetParameter(index, params);
187bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
188bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
189bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
190bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberOMX_ERRORTYPE SoftVorbis::internalSetParameter(
191bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_INDEXTYPE index, const OMX_PTR params) {
192bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    switch (index) {
193bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case OMX_IndexParamStandardComponentRole:
194bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
195bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
196bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                (const OMX_PARAM_COMPONENTROLETYPE *)params;
197bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
198bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (strncmp((const char *)roleParams->cRole,
199bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                        "audio_decoder.vorbis",
200bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                        OMX_MAX_STRINGNAME_SIZE - 1)) {
201bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return OMX_ErrorUndefined;
202bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
203bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
204bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return OMX_ErrorNone;
205bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
206bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
207bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case OMX_IndexParamAudioVorbis:
208bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
209bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            const OMX_AUDIO_PARAM_VORBISTYPE *vorbisParams =
210bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                (const OMX_AUDIO_PARAM_VORBISTYPE *)params;
211bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
212bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (vorbisParams->nPortIndex != 0) {
213bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return OMX_ErrorUndefined;
214bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
215bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
216bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return OMX_ErrorNone;
217bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
218bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
219bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        default:
220bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return SimpleSoftOMXComponent::internalSetParameter(index, params);
221bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
222bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
223bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
224bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberbool SoftVorbis::isConfigured() const {
225bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    return mInputBufferCount >= 2;
226bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
227bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
228bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberstatic void makeBitReader(
229bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const void *data, size_t size,
230bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ogg_buffer *buf, ogg_reference *ref, oggpack_buffer *bits) {
231bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    buf->data = (uint8_t *)data;
232bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    buf->size = size;
233bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    buf->refcount = 1;
234bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    buf->ptr.owner = NULL;
235bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
236bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    ref->buffer = buf;
237bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    ref->begin = 0;
238bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    ref->length = size;
239bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    ref->next = NULL;
240bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
241bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    oggpack_readinit(bits, ref);
242bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
243bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
244bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftVorbis::onQueueFilled(OMX_U32 portIndex) {
245bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    List<BufferInfo *> &inQueue = getPortQueue(0);
246bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    List<BufferInfo *> &outQueue = getPortQueue(1);
247bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
248bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (mOutputPortSettingsChange != NONE) {
249bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        return;
250bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
251bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
252bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (portIndex == 0 && mInputBufferCount < 2) {
253bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        BufferInfo *info = *inQueue.begin();
254bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_BUFFERHEADERTYPE *header = info->mHeader;
255bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
256bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const uint8_t *data = header->pBuffer + header->nOffset;
257bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        size_t size = header->nFilledLen;
258bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
259bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ogg_buffer buf;
260bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ogg_reference ref;
261bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        oggpack_buffer bits;
262bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
263bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        makeBitReader(
264bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                (const uint8_t *)data + 7, size - 7,
265bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                &buf, &ref, &bits);
266bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
267bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if (mInputBufferCount == 0) {
268bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK(mVi == NULL);
269bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mVi = new vorbis_info;
270bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            vorbis_info_init(mVi);
271bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
272bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK_EQ(0, _vorbis_unpack_info(mVi, &bits));
273bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        } else {
274bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK_EQ(0, _vorbis_unpack_books(mVi, &bits));
275bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
276bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK(mState == NULL);
277bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mState = new vorbis_dsp_state;
278bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK_EQ(0, vorbis_dsp_init(mState, mVi));
279bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
280bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
281bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mOutputPortSettingsChange = AWAITING_DISABLED;
282bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
283bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
284bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        inQueue.erase(inQueue.begin());
285bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        info->mOwnedByUs = false;
286bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        notifyEmptyBufferDone(header);
287bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
288bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ++mInputBufferCount;
289bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
290bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        return;
291bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
292bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
293bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    while (!inQueue.empty() && !outQueue.empty()) {
294bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        BufferInfo *inInfo = *inQueue.begin();
295bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
296bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
297bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        BufferInfo *outInfo = *outQueue.begin();
298bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
299bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
300bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
301bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            inQueue.erase(inQueue.begin());
302bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            inInfo->mOwnedByUs = false;
303bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            notifyEmptyBufferDone(inHeader);
304bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
305bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outHeader->nFilledLen = 0;
306bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
307bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
308bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outQueue.erase(outQueue.begin());
309bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            outInfo->mOwnedByUs = false;
310bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            notifyFillBufferDone(outHeader);
311bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return;
312bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
313bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
314bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        int32_t numPageSamples;
315bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        CHECK_GE(inHeader->nFilledLen, sizeof(numPageSamples));
316bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        memcpy(&numPageSamples,
317bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber               inHeader->pBuffer
318bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                + inHeader->nOffset + inHeader->nFilledLen - 4,
319bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber               sizeof(numPageSamples));
320bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
321bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if (numPageSamples >= 0) {
322bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mNumFramesLeftOnPage = numPageSamples;
323bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
324bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
325bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if (inHeader->nOffset == 0) {
326bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mAnchorTimeUs = inHeader->nTimeStamp;
327bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mNumFramesOutput = 0;
328bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
329bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
330bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        inHeader->nFilledLen -= sizeof(numPageSamples);;
331bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
332bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ogg_buffer buf;
333bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        buf.data = inHeader->pBuffer + inHeader->nOffset;
334bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        buf.size = inHeader->nFilledLen;
335bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        buf.refcount = 1;
336bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        buf.ptr.owner = NULL;
337bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
338bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ogg_reference ref;
339bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ref.buffer = &buf;
340bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ref.begin = 0;
341bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ref.length = buf.size;
342bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ref.next = NULL;
343bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
344bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ogg_packet pack;
345bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        pack.packet = &ref;
346bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        pack.bytes = ref.length;
347bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        pack.b_o_s = 0;
348bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        pack.e_o_s = 0;
349bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        pack.granulepos = 0;
350bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        pack.packetno = 0;
351bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
352bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        int numFrames = 0;
353bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
354bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        int err = vorbis_dsp_synthesis(mState, &pack, 1);
355bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if (err != 0) {
3565ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block            ALOGW("vorbis_dsp_synthesis returned %d", err);
357bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        } else {
358bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            numFrames = vorbis_dsp_pcmout(
359bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                    mState, (int16_t *)outHeader->pBuffer,
360bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                    kMaxNumSamplesPerBuffer);
361bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
362bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (numFrames < 0) {
36329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("vorbis_dsp_pcmout returned %d", numFrames);
364bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                numFrames = 0;
365bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
366bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
367bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
368bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if (mNumFramesLeftOnPage >= 0) {
369bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (numFrames > mNumFramesLeftOnPage) {
3703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("discarding %d frames at end of page",
371bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                     numFrames - mNumFramesLeftOnPage);
372bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                numFrames = mNumFramesLeftOnPage;
373bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
374bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mNumFramesLeftOnPage -= numFrames;
375bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
376bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
377bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outHeader->nFilledLen = numFrames * sizeof(int16_t) * mVi->channels;
378bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outHeader->nOffset = 0;
379bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outHeader->nFlags = 0;
380bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
381bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outHeader->nTimeStamp =
382bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mAnchorTimeUs
383bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                + (mNumFramesOutput * 1000000ll) / mVi->rate;
384bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
385bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mNumFramesOutput += numFrames;
386bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
387bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        inInfo->mOwnedByUs = false;
388bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        inQueue.erase(inQueue.begin());
389bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        inInfo = NULL;
390bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        notifyEmptyBufferDone(inHeader);
391bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        inHeader = NULL;
392bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
393bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outInfo->mOwnedByUs = false;
394bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outQueue.erase(outQueue.begin());
395bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outInfo = NULL;
396bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        notifyFillBufferDone(outHeader);
397bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outHeader = NULL;
398bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
399bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ++mInputBufferCount;
400bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
401bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
402bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
403bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftVorbis::onPortFlushCompleted(OMX_U32 portIndex) {
404bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (portIndex == 0 && mState != NULL) {
405bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        // Make sure that the next buffer output does not still
406bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        // depend on fragments from the last one decoded.
407bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
408bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mNumFramesOutput = 0;
409bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        vorbis_dsp_restart(mState);
410bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
411bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
412bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
413bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftVorbis::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
414bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (portIndex != 1) {
415bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        return;
416bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
417bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
418bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    switch (mOutputPortSettingsChange) {
419bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case NONE:
420bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            break;
421bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
422bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case AWAITING_DISABLED:
423bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
424bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK(!enabled);
425bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mOutputPortSettingsChange = AWAITING_ENABLED;
426bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            break;
427bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
428bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
429bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        default:
430bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
431bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
432bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK(enabled);
433bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mOutputPortSettingsChange = NONE;
434bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            break;
435bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
436bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
437bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
438bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
439bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}  // namespace android
440bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
441bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberandroid::SoftOMXComponent *createSoftOMXComponent(
442bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const char *name, const OMX_CALLBACKTYPE *callbacks,
443bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
444bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    return new android::SoftVorbis(name, callbacks, appData, component);
445bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
446