1ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen/*
2ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * Copyright (C) 2012 The Android Open Source Project
3ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen *
4ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * Licensed under the Apache License, Version 2.0 (the "License");
5ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * you may not use this file except in compliance with the License.
6ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * You may obtain a copy of the License at
7ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen *
8ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen *      http://www.apache.org/licenses/LICENSE-2.0
9ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen *
10ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * Unless required by applicable law or agreed to in writing, software
11ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * distributed under the License is distributed on an "AS IS" BASIS,
12ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * See the License for the specific language governing permissions and
14ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen * limitations under the License.
15ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen */
16ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
17ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen//#define LOG_NDEBUG 0
18ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen#define LOG_TAG "SoftGSM"
19ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen#include <utils/Log.h>
20ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
21ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen#include "SoftGSM.h"
22ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
23ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen#include <media/stagefright/foundation/ADebug.h>
24ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen#include <media/stagefright/MediaDefs.h>
25ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
26ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissennamespace android {
27ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
28ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissentemplate<class T>
29ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissenstatic void InitOMXParams(T *params) {
30ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    params->nSize = sizeof(T);
31ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    params->nVersion.s.nVersionMajor = 1;
32ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    params->nVersion.s.nVersionMinor = 0;
33ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    params->nVersion.s.nRevision = 0;
34ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    params->nVersion.s.nStep = 0;
35ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen}
36ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
37ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco NelissenSoftGSM::SoftGSM(
38ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        const char *name,
39ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        const OMX_CALLBACKTYPE *callbacks,
40ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        OMX_PTR appData,
41ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        OMX_COMPONENTTYPE **component)
42ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    : SimpleSoftOMXComponent(name, callbacks, appData, component),
43ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen      mSignalledError(false) {
44ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
45ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    CHECK(!strcmp(name, "OMX.google.gsm.decoder"));
46ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
47ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    mGsm = gsm_create();
48ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    CHECK(mGsm);
49ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    int msopt = 1;
50ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    gsm_option(mGsm, GSM_OPT_WAV49, &msopt);
51ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
52ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    initPorts();
53ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen}
54ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
55ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco NelissenSoftGSM::~SoftGSM() {
56ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    gsm_destroy(mGsm);
57ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen}
58ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
59ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissenvoid SoftGSM::initPorts() {
60ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    OMX_PARAM_PORTDEFINITIONTYPE def;
61ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    InitOMXParams(&def);
62ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
63ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.nPortIndex = 0;
64ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.eDir = OMX_DirInput;
65ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.nBufferCountMin = kNumBuffers;
66ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.nBufferCountActual = def.nBufferCountMin;
67ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.nBufferSize = sizeof(gsm_frame);
68ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.bEnabled = OMX_TRUE;
69ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.bPopulated = OMX_FALSE;
70ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.eDomain = OMX_PortDomainAudio;
71ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.bBuffersContiguous = OMX_FALSE;
72ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.nBufferAlignment = 1;
73ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
74ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.format.audio.cMIMEType =
75ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        const_cast<char *>(MEDIA_MIMETYPE_AUDIO_MSGSM);
76ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
77ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.format.audio.pNativeRender = NULL;
78ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
79ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.format.audio.eEncoding = OMX_AUDIO_CodingGSMFR;
80ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
81ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    addPort(def);
82ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
83ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.nPortIndex = 1;
84ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.eDir = OMX_DirOutput;
85ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.nBufferCountMin = kNumBuffers;
86ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.nBufferCountActual = def.nBufferCountMin;
87ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.nBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t);
88ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.bEnabled = OMX_TRUE;
89ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.bPopulated = OMX_FALSE;
90ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.eDomain = OMX_PortDomainAudio;
91ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.bBuffersContiguous = OMX_FALSE;
92ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.nBufferAlignment = 2;
93ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
94ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
95ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.format.audio.pNativeRender = NULL;
96ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
97ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
98ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
99ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    addPort(def);
100ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen}
101ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
102ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco NelissenOMX_ERRORTYPE SoftGSM::internalGetParameter(
103ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        OMX_INDEXTYPE index, OMX_PTR params) {
104ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    switch (index) {
105ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        case OMX_IndexParamAudioPcm:
106ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        {
107ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
108ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
109ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
110ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            if (pcmParams->nPortIndex > 1) {
111ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen                return OMX_ErrorUndefined;
112ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            }
113ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
114ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            pcmParams->eNumData = OMX_NumericalDataSigned;
115ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            pcmParams->eEndian = OMX_EndianBig;
116ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            pcmParams->bInterleaved = OMX_TRUE;
117ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            pcmParams->nBitPerSample = 16;
118ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
119ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
120ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
121ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
122ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            pcmParams->nChannels = 1;
123ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            pcmParams->nSamplingRate = 8000;
124ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
125ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            return OMX_ErrorNone;
126ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        }
127ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
128ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        default:
129ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            return SimpleSoftOMXComponent::internalGetParameter(index, params);
130ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    }
131ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen}
132ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
133ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco NelissenOMX_ERRORTYPE SoftGSM::internalSetParameter(
134ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        OMX_INDEXTYPE index, const OMX_PTR params) {
135ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    switch (index) {
136ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        case OMX_IndexParamAudioPcm:
137ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        {
138ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
139ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
140ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
141ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
142ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen                return OMX_ErrorUndefined;
143ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            }
144ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
145ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            if (pcmParams->nChannels != 1) {
146ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen                return OMX_ErrorUndefined;
147ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            }
148ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
149ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            if (pcmParams->nSamplingRate != 8000) {
150ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen                return OMX_ErrorUndefined;
151ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            }
152ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
153ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            return OMX_ErrorNone;
154ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        }
155ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
156ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        case OMX_IndexParamStandardComponentRole:
157ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        {
158ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
159ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen                (const OMX_PARAM_COMPONENTROLETYPE *)params;
160ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
161ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            if (strncmp((const char *)roleParams->cRole,
162ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen                        "audio_decoder.gsm",
163ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen                        OMX_MAX_STRINGNAME_SIZE - 1)) {
164ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen                return OMX_ErrorUndefined;
165ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            }
166ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
167ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            return OMX_ErrorNone;
168ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        }
169ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
170ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        default:
171ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            return SimpleSoftOMXComponent::internalSetParameter(index, params);
172ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    }
173ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen}
174ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
17584333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftGSM::onQueueFilled(OMX_U32 /* portIndex */) {
176ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    if (mSignalledError) {
177ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        return;
178ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    }
179ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
180ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    List<BufferInfo *> &inQueue = getPortQueue(0);
181ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    List<BufferInfo *> &outQueue = getPortQueue(1);
182ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
183ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    while (!inQueue.empty() && !outQueue.empty()) {
184ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        BufferInfo *inInfo = *inQueue.begin();
185ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
186ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
187ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        BufferInfo *outInfo = *outQueue.begin();
188ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
189ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
190ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
191ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            inQueue.erase(inQueue.begin());
192ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            inInfo->mOwnedByUs = false;
193ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            notifyEmptyBufferDone(inHeader);
194ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
195ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            outHeader->nFilledLen = 0;
196ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
197ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
198ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            outQueue.erase(outQueue.begin());
199ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            outInfo->mOwnedByUs = false;
200ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            notifyFillBufferDone(outHeader);
201ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            return;
202ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        }
203ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
204ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        if (inHeader->nFilledLen > kMaxNumSamplesPerFrame) {
20566fe2e9ee30bcb4161bc487ec63d2ae4a05f4051Glenn Kasten            ALOGE("input buffer too large (%d).", inHeader->nFilledLen);
206ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
207ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            mSignalledError = true;
208ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        }
209ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
210ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        if(((inHeader->nFilledLen / 65) * 65) != inHeader->nFilledLen) {
21166fe2e9ee30bcb4161bc487ec63d2ae4a05f4051Glenn Kasten            ALOGE("input buffer not multiple of 65 (%d).", inHeader->nFilledLen);
212ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
213ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen            mSignalledError = true;
214ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        }
215ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
216ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        uint8_t *inputptr = inHeader->pBuffer + inHeader->nOffset;
217ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
218ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        int n = mSignalledError ? 0 : DecodeGSM(mGsm,
219ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen                  reinterpret_cast<int16_t *>(outHeader->pBuffer), inputptr, inHeader->nFilledLen);
220ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
221ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        outHeader->nTimeStamp = inHeader->nTimeStamp;
222ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        outHeader->nOffset = 0;
223ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        outHeader->nFilledLen = n * sizeof(int16_t);
224ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        outHeader->nFlags = 0;
225ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
226ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        inInfo->mOwnedByUs = false;
227ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        inQueue.erase(inQueue.begin());
228ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        inInfo = NULL;
229ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        notifyEmptyBufferDone(inHeader);
230ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        inHeader = NULL;
231ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
232ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        outInfo->mOwnedByUs = false;
233ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        outQueue.erase(outQueue.begin());
234ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        outInfo = NULL;
235ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        notifyFillBufferDone(outHeader);
236ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        outHeader = NULL;
237ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    }
238ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen}
239ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
240ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
241ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen// static
242ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissenint SoftGSM::DecodeGSM(gsm handle,
243ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        int16_t *out, uint8_t *in, size_t inSize) {
244ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
245ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    int ret = 0;
246ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    while (inSize > 0) {
247ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        gsm_decode(handle, in, out);
248ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        in += 33;
249ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        inSize -= 33;
250ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        out += 160;
251ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        ret += 160;
252ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        gsm_decode(handle, in, out);
253ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        in += 32;
254ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        inSize -= 32;
255ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        out += 160;
256ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        ret += 160;
257ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    }
258ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    return ret;
259ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen}
260ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
261ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
262ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen}  // namespace android
263ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
264ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissenandroid::SoftOMXComponent *createSoftOMXComponent(
265ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        const char *name, const OMX_CALLBACKTYPE *callbacks,
266ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
267ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen    return new android::SoftGSM(name, callbacks, appData, component);
268ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen}
269ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen
270