12ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen/*
22ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * Copyright (C) 2012 The Android Open Source Project
32ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen *
42ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * Licensed under the Apache License, Version 2.0 (the "License");
52ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * you may not use this file except in compliance with the License.
62ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * You may obtain a copy of the License at
72ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen *
82ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen *      http://www.apache.org/licenses/LICENSE-2.0
92ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen *
102ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * Unless required by applicable law or agreed to in writing, software
112ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * distributed under the License is distributed on an "AS IS" BASIS,
122ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * See the License for the specific language governing permissions and
142ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen * limitations under the License.
152ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen */
162ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
172ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen//#define LOG_NDEBUG 0
182ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen#define LOG_TAG "SoftGSM"
192ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen#include <utils/Log.h>
202ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
212ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen#include "SoftGSM.h"
222ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
232ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen#include <media/stagefright/foundation/ADebug.h>
242ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen#include <media/stagefright/MediaDefs.h>
252ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
262ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissennamespace android {
272ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
282ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissentemplate<class T>
292ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissenstatic void InitOMXParams(T *params) {
302ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    params->nSize = sizeof(T);
312ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    params->nVersion.s.nVersionMajor = 1;
322ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    params->nVersion.s.nVersionMinor = 0;
332ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    params->nVersion.s.nRevision = 0;
342ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    params->nVersion.s.nStep = 0;
352ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen}
362ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
37cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen// Microsoft WAV GSM encoding packs two GSM frames into 65 bytes.
38cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissenstatic const int kMSGSMFrameSize = 65;
39cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen
402ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco NelissenSoftGSM::SoftGSM(
412ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        const char *name,
422ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        const OMX_CALLBACKTYPE *callbacks,
432ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        OMX_PTR appData,
442ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        OMX_COMPONENTTYPE **component)
452ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    : SimpleSoftOMXComponent(name, callbacks, appData, component),
462ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen      mSignalledError(false) {
472ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
482ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    CHECK(!strcmp(name, "OMX.google.gsm.decoder"));
492ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
502ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    mGsm = gsm_create();
512ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    CHECK(mGsm);
522ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    int msopt = 1;
532ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    gsm_option(mGsm, GSM_OPT_WAV49, &msopt);
542ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
552ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    initPorts();
562ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen}
572ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
582ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco NelissenSoftGSM::~SoftGSM() {
592ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    gsm_destroy(mGsm);
602ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen}
612ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
622ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissenvoid SoftGSM::initPorts() {
632ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    OMX_PARAM_PORTDEFINITIONTYPE def;
642ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    InitOMXParams(&def);
652ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
662ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.nPortIndex = 0;
672ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.eDir = OMX_DirInput;
682ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.nBufferCountMin = kNumBuffers;
692ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.nBufferCountActual = def.nBufferCountMin;
70cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen    def.nBufferSize = 1024 / kMSGSMFrameSize * kMSGSMFrameSize;
712ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.bEnabled = OMX_TRUE;
722ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.bPopulated = OMX_FALSE;
732ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.eDomain = OMX_PortDomainAudio;
742ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.bBuffersContiguous = OMX_FALSE;
752ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.nBufferAlignment = 1;
762ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
772ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.format.audio.cMIMEType =
782ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        const_cast<char *>(MEDIA_MIMETYPE_AUDIO_MSGSM);
792ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
802ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.format.audio.pNativeRender = NULL;
812ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
822ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.format.audio.eEncoding = OMX_AUDIO_CodingGSMFR;
832ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
842ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    addPort(def);
852ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
862ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.nPortIndex = 1;
872ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.eDir = OMX_DirOutput;
882ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.nBufferCountMin = kNumBuffers;
892ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.nBufferCountActual = def.nBufferCountMin;
902ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.nBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t);
912ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.bEnabled = OMX_TRUE;
922ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.bPopulated = OMX_FALSE;
932ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.eDomain = OMX_PortDomainAudio;
942ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.bBuffersContiguous = OMX_FALSE;
952ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.nBufferAlignment = 2;
962ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
972ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
982ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.format.audio.pNativeRender = NULL;
992ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
1002ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
1012ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
1022ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    addPort(def);
1032ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen}
1042ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
1052ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco NelissenOMX_ERRORTYPE SoftGSM::internalGetParameter(
1062ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        OMX_INDEXTYPE index, OMX_PTR params) {
1072ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    switch (index) {
1081e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan        case OMX_IndexParamAudioPortFormat:
1091e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan        {
1101e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
1111e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
1121e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan
1131e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            if (!isValidOMXParam(formatParams)) {
1141e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan                return OMX_ErrorBadParameter;
1151e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            }
1161e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan
1171e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            if (formatParams->nPortIndex > 1) {
1181e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan                return OMX_ErrorUndefined;
1191e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            }
1201e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan
1211e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            if (formatParams->nIndex > 0) {
1221e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan                return OMX_ErrorNoMore;
1231e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            }
1241e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan
1251e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            formatParams->eEncoding =
1261e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan                (formatParams->nPortIndex == 0)
1271e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan                    ? OMX_AUDIO_CodingGSMFR : OMX_AUDIO_CodingPCM;
1281e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan
1291e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            return OMX_ErrorNone;
1301e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan        }
1311e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan
1322ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        case OMX_IndexParamAudioPcm:
1332ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        {
1342ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
1352ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
1362ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
137f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            if (!isValidOMXParam(pcmParams)) {
138f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen                return OMX_ErrorBadParameter;
139f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            }
140f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen
1412ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            if (pcmParams->nPortIndex > 1) {
1422ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen                return OMX_ErrorUndefined;
1432ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            }
1442ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
1452ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            pcmParams->eNumData = OMX_NumericalDataSigned;
1462ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            pcmParams->eEndian = OMX_EndianBig;
1472ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            pcmParams->bInterleaved = OMX_TRUE;
1482ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            pcmParams->nBitPerSample = 16;
1492ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
1502ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
1512ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
1522ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
1532ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            pcmParams->nChannels = 1;
1542ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            pcmParams->nSamplingRate = 8000;
1552ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
1562ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            return OMX_ErrorNone;
1572ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        }
1582ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
1592ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        default:
1602ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            return SimpleSoftOMXComponent::internalGetParameter(index, params);
1612ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    }
1622ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen}
1632ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
1642ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco NelissenOMX_ERRORTYPE SoftGSM::internalSetParameter(
1652ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        OMX_INDEXTYPE index, const OMX_PTR params) {
1662ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    switch (index) {
1672ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        case OMX_IndexParamAudioPcm:
1682ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        {
1692ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
1702ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
1712ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
172f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            if (!isValidOMXParam(pcmParams)) {
173f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen                return OMX_ErrorBadParameter;
174f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            }
175f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen
1762ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            if (pcmParams->nPortIndex != 0 && pcmParams->nPortIndex != 1) {
1772ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen                return OMX_ErrorUndefined;
1782ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            }
1792ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
1802ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            if (pcmParams->nChannels != 1) {
1812ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen                return OMX_ErrorUndefined;
1822ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            }
1832ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
1842ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            if (pcmParams->nSamplingRate != 8000) {
1852ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen                return OMX_ErrorUndefined;
1862ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            }
1872ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
1882ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            return OMX_ErrorNone;
1892ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        }
1902ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
1911e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan        case OMX_IndexParamAudioPortFormat:
1921e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan        {
1931e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
1941e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
1951e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan
1961e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            if (!isValidOMXParam(formatParams)) {
1971e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan                return OMX_ErrorBadParameter;
1981e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            }
1991e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan
2001e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            if (formatParams->nPortIndex > 1) {
2011e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan                return OMX_ErrorUndefined;
2021e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            }
2031e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan
2041e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            if ((formatParams->nPortIndex == 0
2051e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan                        && formatParams->eEncoding != OMX_AUDIO_CodingGSMFR)
2061e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan                || (formatParams->nPortIndex == 1
2071e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
2081e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan                return OMX_ErrorUndefined;
2091e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            }
2101e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan
2111e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan            return OMX_ErrorNone;
2121e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan        }
2131e73885bceac69f2b08987e36aad651c824fbd65Ram Mohan
2142ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        case OMX_IndexParamStandardComponentRole:
2152ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        {
2162ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
2172ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen                (const OMX_PARAM_COMPONENTROLETYPE *)params;
2182ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
219f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            if (!isValidOMXParam(roleParams)) {
220f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen                return OMX_ErrorBadParameter;
221f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            }
222f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen
2232ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            if (strncmp((const char *)roleParams->cRole,
2242ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen                        "audio_decoder.gsm",
2252ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen                        OMX_MAX_STRINGNAME_SIZE - 1)) {
2262ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen                return OMX_ErrorUndefined;
2272ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            }
2282ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
2292ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            return OMX_ErrorNone;
2302ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        }
2312ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
2322ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        default:
2332ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            return SimpleSoftOMXComponent::internalSetParameter(index, params);
2342ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    }
2352ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen}
2362ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
237d411b4ca2945cd8974a3a78199fce94646950128Andreas Hubervoid SoftGSM::onQueueFilled(OMX_U32 /* portIndex */) {
2382ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    if (mSignalledError) {
2392ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        return;
2402ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    }
2412ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
2422ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    List<BufferInfo *> &inQueue = getPortQueue(0);
2432ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    List<BufferInfo *> &outQueue = getPortQueue(1);
2442ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
2452ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    while (!inQueue.empty() && !outQueue.empty()) {
2462ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        BufferInfo *inInfo = *inQueue.begin();
2472ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
2482ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
2492ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        BufferInfo *outInfo = *outQueue.begin();
2502ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
2512ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
252199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia        if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) {
2532ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            inQueue.erase(inQueue.begin());
2542ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            inInfo->mOwnedByUs = false;
2552ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            notifyEmptyBufferDone(inHeader);
2562ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
2572ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            outHeader->nFilledLen = 0;
2582ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
2592ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
2602ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            outQueue.erase(outQueue.begin());
2612ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            outInfo->mOwnedByUs = false;
2622ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            notifyFillBufferDone(outHeader);
2632ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            return;
2642ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        }
2652ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
2662ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        if (inHeader->nFilledLen > kMaxNumSamplesPerFrame) {
26766fe2e9ee30bcb4161bc487ec63d2ae4a05f4051Glenn Kasten            ALOGE("input buffer too large (%d).", inHeader->nFilledLen);
2682ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
2692ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            mSignalledError = true;
2702ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        }
2712ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
272cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen        if(((inHeader->nFilledLen / kMSGSMFrameSize) * kMSGSMFrameSize) != inHeader->nFilledLen) {
273cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen            ALOGE("input buffer not multiple of %d (%d).", kMSGSMFrameSize, inHeader->nFilledLen);
2742ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
2752ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen            mSignalledError = true;
2762ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        }
2772ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
278d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim        if (outHeader->nAllocLen < (inHeader->nFilledLen / kMSGSMFrameSize) * 320) {
279d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim            ALOGE("output buffer is not large enough (%d).", outHeader->nAllocLen);
280d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim            android_errorWriteLog(0x534e4554, "27793367");
281d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim            notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
282d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim            mSignalledError = true;
283d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim            return;
284d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim        }
285d211045926b78d2bc82611c97a7cfd18a9790c4bWonsik Kim
2862ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        uint8_t *inputptr = inHeader->pBuffer + inHeader->nOffset;
2872ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
2882ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        int n = mSignalledError ? 0 : DecodeGSM(mGsm,
2892ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen                  reinterpret_cast<int16_t *>(outHeader->pBuffer), inputptr, inHeader->nFilledLen);
2902ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
2912ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        outHeader->nTimeStamp = inHeader->nTimeStamp;
2922ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        outHeader->nOffset = 0;
2932ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        outHeader->nFilledLen = n * sizeof(int16_t);
2942ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        outHeader->nFlags = 0;
2952ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
296199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia        if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
297199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia            inHeader->nFilledLen = 0;
298199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia        } else {
299199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia            inInfo->mOwnedByUs = false;
300199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia            inQueue.erase(inQueue.begin());
301199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia            inInfo = NULL;
302199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia            notifyEmptyBufferDone(inHeader);
303199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia            inHeader = NULL;
304199a6e3682c2804975ef8b56159bbc31426ef3d4Wei Jia        }
3052ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
3062ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        outInfo->mOwnedByUs = false;
3072ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        outQueue.erase(outQueue.begin());
3082ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        outInfo = NULL;
3092ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        notifyFillBufferDone(outHeader);
3102ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        outHeader = NULL;
3112ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    }
3122ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen}
3132ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
3142ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
3152ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen// static
3162ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissenint SoftGSM::DecodeGSM(gsm handle,
3172ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        int16_t *out, uint8_t *in, size_t inSize) {
3182ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
3192ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    int ret = 0;
3202ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    while (inSize > 0) {
3212ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        gsm_decode(handle, in, out);
3222ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        in += 33;
3232ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        inSize -= 33;
3242ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        out += 160;
3252ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        ret += 160;
3262ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        gsm_decode(handle, in, out);
3272ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        in += 32;
3282ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        inSize -= 32;
3292ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        out += 160;
3302ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        ret += 160;
3312ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    }
3322ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    return ret;
3332ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen}
3342ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
335cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissenvoid SoftGSM::onPortFlushCompleted(OMX_U32 portIndex) {
336cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen    if (portIndex == 0) {
337cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen        gsm_destroy(mGsm);
338cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen        mGsm = gsm_create();
339cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen        int msopt = 1;
340cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen        gsm_option(mGsm, GSM_OPT_WAV49, &msopt);
341cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen    }
342cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen}
343cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen
344cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissenvoid SoftGSM::onReset() {
345cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen    gsm_destroy(mGsm);
346cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen    mGsm = gsm_create();
347cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen    int msopt = 1;
348cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen    gsm_option(mGsm, GSM_OPT_WAV49, &msopt);
349cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen    mSignalledError = false;
350cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen}
351cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen
352cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen
353cafe4d8511d4e8185d177b367c1f0b764f9a1789Marco Nelissen
3542ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
3552ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen}  // namespace android
3562ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
3572ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissenandroid::SoftOMXComponent *createSoftOMXComponent(
3582ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        const char *name, const OMX_CALLBACKTYPE *callbacks,
3592ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
3602ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen    return new android::SoftGSM(name, callbacks, appData, component);
3612ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen}
3622ed5cf016c1b45426ae25ab105e02ff4bb992f28Marco Nelissen
363