Home | History | Annotate | Download | only in dec
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define LOG_TAG "SoftVorbis"
     19 #include <utils/Log.h>
     20 
     21 #include "SoftVorbis.h"
     22 
     23 #include <media/stagefright/foundation/ADebug.h>
     24 #include <media/stagefright/MediaDefs.h>
     25 
     26 static int kDefaultChannelCount = 1;
     27 static int kDefaultSamplingRate = 48000;
     28 
     29 extern "C" {
     30     #include <Tremolo/codec_internal.h>
     31 
     32     int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
     33     int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
     34     int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
     35 }
     36 
     37 namespace android {
     38 
     39 template<class T>
     40 static void InitOMXParams(T *params) {
     41     params->nSize = sizeof(T);
     42     params->nVersion.s.nVersionMajor = 1;
     43     params->nVersion.s.nVersionMinor = 0;
     44     params->nVersion.s.nRevision = 0;
     45     params->nVersion.s.nStep = 0;
     46 }
     47 
     48 SoftVorbis::SoftVorbis(
     49         const char *name,
     50         const OMX_CALLBACKTYPE *callbacks,
     51         OMX_PTR appData,
     52         OMX_COMPONENTTYPE **component)
     53     : SimpleSoftOMXComponent(name, callbacks, appData, component),
     54       mInputBufferCount(0),
     55       mState(NULL),
     56       mVi(NULL),
     57       mAnchorTimeUs(0),
     58       mNumFramesOutput(0),
     59       mNumFramesLeftOnPage(-1),
     60       mSawInputEos(false),
     61       mSignalledOutputEos(false),
     62       mSignalledError(false),
     63       mOutputPortSettingsChange(NONE) {
     64     initPorts();
     65     CHECK_EQ(initDecoder(), (status_t)OK);
     66 }
     67 
     68 SoftVorbis::~SoftVorbis() {
     69     if (mState != NULL) {
     70         vorbis_dsp_clear(mState);
     71         delete mState;
     72         mState = NULL;
     73     }
     74 
     75     if (mVi != NULL) {
     76         vorbis_info_clear(mVi);
     77         delete mVi;
     78         mVi = NULL;
     79     }
     80 }
     81 
     82 void SoftVorbis::initPorts() {
     83     OMX_PARAM_PORTDEFINITIONTYPE def;
     84     InitOMXParams(&def);
     85 
     86     def.nPortIndex = 0;
     87     def.eDir = OMX_DirInput;
     88     def.nBufferCountMin = kNumBuffers;
     89     def.nBufferCountActual = def.nBufferCountMin;
     90     def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t);
     91     def.bEnabled = OMX_TRUE;
     92     def.bPopulated = OMX_FALSE;
     93     def.eDomain = OMX_PortDomainAudio;
     94     def.bBuffersContiguous = OMX_FALSE;
     95     def.nBufferAlignment = 1;
     96 
     97     def.format.audio.cMIMEType =
     98         const_cast<char *>(MEDIA_MIMETYPE_AUDIO_VORBIS);
     99 
    100     def.format.audio.pNativeRender = NULL;
    101     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
    102     def.format.audio.eEncoding = OMX_AUDIO_CodingVORBIS;
    103 
    104     addPort(def);
    105 
    106     def.nPortIndex = 1;
    107     def.eDir = OMX_DirOutput;
    108     def.nBufferCountMin = kNumBuffers;
    109     def.nBufferCountActual = def.nBufferCountMin;
    110     def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t);
    111     def.bEnabled = OMX_TRUE;
    112     def.bPopulated = OMX_FALSE;
    113     def.eDomain = OMX_PortDomainAudio;
    114     def.bBuffersContiguous = OMX_FALSE;
    115     def.nBufferAlignment = 2;
    116 
    117     def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
    118     def.format.audio.pNativeRender = NULL;
    119     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
    120     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
    121 
    122     addPort(def);
    123 }
    124 
    125 status_t SoftVorbis::initDecoder() {
    126     return OK;
    127 }
    128 
    129 OMX_ERRORTYPE SoftVorbis::internalGetParameter(
    130         OMX_INDEXTYPE index, OMX_PTR params) {
    131     switch (index) {
    132         case OMX_IndexParamAudioPortFormat:
    133         {
    134             OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
    135                 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
    136 
    137             if (!isValidOMXParam(formatParams)) {
    138                 return OMX_ErrorBadParameter;
    139             }
    140 
    141             if (formatParams->nPortIndex > 1) {
    142                 return OMX_ErrorUndefined;
    143             }
    144 
    145             if (formatParams->nIndex > 0) {
    146                 return OMX_ErrorNoMore;
    147             }
    148 
    149             formatParams->eEncoding =
    150                 (formatParams->nPortIndex == 0)
    151                     ? OMX_AUDIO_CodingVORBIS : OMX_AUDIO_CodingPCM;
    152 
    153             return OMX_ErrorNone;
    154         }
    155 
    156         case OMX_IndexParamAudioVorbis:
    157         {
    158             OMX_AUDIO_PARAM_VORBISTYPE *vorbisParams =
    159                 (OMX_AUDIO_PARAM_VORBISTYPE *)params;
    160 
    161             if (!isValidOMXParam(vorbisParams)) {
    162                 return OMX_ErrorBadParameter;
    163             }
    164 
    165             if (vorbisParams->nPortIndex != 0) {
    166                 return OMX_ErrorUndefined;
    167             }
    168 
    169             vorbisParams->nBitRate = 0;
    170             vorbisParams->nMinBitRate = 0;
    171             vorbisParams->nMaxBitRate = 0;
    172             vorbisParams->nAudioBandWidth = 0;
    173             vorbisParams->nQuality = 3;
    174             vorbisParams->bManaged = OMX_FALSE;
    175             vorbisParams->bDownmix = OMX_FALSE;
    176 
    177             if (!isConfigured()) {
    178                 vorbisParams->nChannels = kDefaultChannelCount;
    179                 vorbisParams->nSampleRate = kDefaultSamplingRate;
    180             } else {
    181                 vorbisParams->nChannels = mVi->channels;
    182                 vorbisParams->nSampleRate = mVi->rate;
    183                 vorbisParams->nBitRate = mVi->bitrate_nominal;
    184                 vorbisParams->nMinBitRate = mVi->bitrate_lower;
    185                 vorbisParams->nMaxBitRate = mVi->bitrate_upper;
    186             }
    187             return OMX_ErrorNone;
    188         }
    189 
    190         case OMX_IndexParamAudioPcm:
    191         {
    192             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
    193                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
    194 
    195             if (!isValidOMXParam(pcmParams)) {
    196                 return OMX_ErrorBadParameter;
    197             }
    198 
    199             if (pcmParams->nPortIndex != 1) {
    200                 return OMX_ErrorUndefined;
    201             }
    202 
    203             pcmParams->eNumData = OMX_NumericalDataSigned;
    204             pcmParams->eEndian = OMX_EndianBig;
    205             pcmParams->bInterleaved = OMX_TRUE;
    206             pcmParams->nBitPerSample = 16;
    207             pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
    208             pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
    209             pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
    210 
    211             if (!isConfigured()) {
    212                 pcmParams->nChannels = kDefaultChannelCount;
    213                 pcmParams->nSamplingRate = kDefaultSamplingRate;
    214             } else {
    215                 pcmParams->nChannels = mVi->channels;
    216                 pcmParams->nSamplingRate = mVi->rate;
    217             }
    218 
    219             return OMX_ErrorNone;
    220         }
    221 
    222         default:
    223             return SimpleSoftOMXComponent::internalGetParameter(index, params);
    224     }
    225 }
    226 
    227 OMX_ERRORTYPE SoftVorbis::internalSetParameter(
    228         OMX_INDEXTYPE index, const OMX_PTR params) {
    229     switch (index) {
    230         case OMX_IndexParamStandardComponentRole:
    231         {
    232             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
    233                 (const OMX_PARAM_COMPONENTROLETYPE *)params;
    234 
    235             if (!isValidOMXParam(roleParams)) {
    236                 return OMX_ErrorBadParameter;
    237             }
    238 
    239             if (strncmp((const char *)roleParams->cRole,
    240                         "audio_decoder.vorbis",
    241                         OMX_MAX_STRINGNAME_SIZE - 1)) {
    242                 return OMX_ErrorUndefined;
    243             }
    244 
    245             return OMX_ErrorNone;
    246         }
    247 
    248         case OMX_IndexParamAudioPortFormat:
    249         {
    250             const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
    251                 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
    252 
    253             if (!isValidOMXParam(formatParams)) {
    254                 return OMX_ErrorBadParameter;
    255             }
    256 
    257             if (formatParams->nPortIndex > 1) {
    258                 return OMX_ErrorUndefined;
    259             }
    260 
    261             if ((formatParams->nPortIndex == 0
    262                         && formatParams->eEncoding != OMX_AUDIO_CodingVORBIS)
    263                 || (formatParams->nPortIndex == 1
    264                         && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
    265                 return OMX_ErrorUndefined;
    266             }
    267 
    268             return OMX_ErrorNone;
    269         }
    270 
    271         case OMX_IndexParamAudioVorbis:
    272         {
    273             const OMX_AUDIO_PARAM_VORBISTYPE *vorbisParams =
    274                 (const OMX_AUDIO_PARAM_VORBISTYPE *)params;
    275 
    276             if (!isValidOMXParam(vorbisParams)) {
    277                 return OMX_ErrorBadParameter;
    278             }
    279 
    280             if (vorbisParams->nPortIndex != 0) {
    281                 return OMX_ErrorUndefined;
    282             }
    283 
    284             return OMX_ErrorNone;
    285         }
    286 
    287         default:
    288             return SimpleSoftOMXComponent::internalSetParameter(index, params);
    289     }
    290 }
    291 
    292 bool SoftVorbis::isConfigured() const {
    293     return mInputBufferCount >= 2;
    294 }
    295 
    296 static void makeBitReader(
    297         const void *data, size_t size,
    298         ogg_buffer *buf, ogg_reference *ref, oggpack_buffer *bits) {
    299     buf->data = (uint8_t *)data;
    300     buf->size = size;
    301     buf->refcount = 1;
    302     buf->ptr.owner = NULL;
    303 
    304     ref->buffer = buf;
    305     ref->begin = 0;
    306     ref->length = size;
    307     ref->next = NULL;
    308 
    309     oggpack_readinit(bits, ref);
    310 }
    311 
    312 void SoftVorbis::handleEOS() {
    313     List<BufferInfo *> &inQueue = getPortQueue(0);
    314     List<BufferInfo *> &outQueue = getPortQueue(1);
    315 
    316     CHECK(!inQueue.empty() && !outQueue.empty());
    317 
    318     mSawInputEos = true;
    319 
    320     BufferInfo *outInfo = *outQueue.begin();
    321     OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
    322     outHeader->nFilledLen = 0;
    323     outHeader->nFlags = OMX_BUFFERFLAG_EOS;
    324 
    325     outQueue.erase(outQueue.begin());
    326     outInfo->mOwnedByUs = false;
    327     notifyFillBufferDone(outHeader);
    328     mSignalledOutputEos = true;
    329 
    330     BufferInfo *inInfo = *inQueue.begin();
    331     OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
    332     inQueue.erase(inQueue.begin());
    333     inInfo->mOwnedByUs = false;
    334     notifyEmptyBufferDone(inHeader);
    335     ++mInputBufferCount;
    336 }
    337 
    338 void SoftVorbis::onQueueFilled(OMX_U32 /* portIndex */) {
    339     List<BufferInfo *> &inQueue = getPortQueue(0);
    340     List<BufferInfo *> &outQueue = getPortQueue(1);
    341 
    342     if (mSignalledError || mOutputPortSettingsChange != NONE) {
    343         return;
    344     }
    345 
    346     while (!mSignalledOutputEos && (!inQueue.empty() || mSawInputEos) && !outQueue.empty()) {
    347         BufferInfo *inInfo = NULL;
    348         OMX_BUFFERHEADERTYPE *inHeader = NULL;
    349         if (!inQueue.empty()) {
    350             inInfo = *inQueue.begin();
    351             inHeader = inInfo->mHeader;
    352         }
    353 
    354         BufferInfo *outInfo = *outQueue.begin();
    355         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
    356 
    357         int32_t numPageSamples = 0;
    358 
    359         if (inHeader) {
    360             if (mInputBufferCount < 2) {
    361                 const uint8_t *data = inHeader->pBuffer + inHeader->nOffset;
    362                 size_t size = inHeader->nFilledLen;
    363 
    364                 if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && size == 0) {
    365                     handleEOS();
    366                     return;
    367                 }
    368 
    369                 if (size < 7) {
    370                     ALOGE("Too small input buffer: %zu bytes", size);
    371                     android_errorWriteLog(0x534e4554, "27833616");
    372                     notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
    373                     mSignalledError = true;
    374                     return;
    375                 }
    376 
    377                 ogg_buffer buf;
    378                 ogg_reference ref;
    379                 oggpack_buffer bits;
    380 
    381                 makeBitReader((const uint8_t *)data + 7, size - 7, &buf, &ref, &bits);
    382 
    383                 if (mInputBufferCount == 0) {
    384                     CHECK(mVi == NULL);
    385                     mVi = new vorbis_info;
    386                     vorbis_info_init(mVi);
    387 
    388                     int ret = _vorbis_unpack_info(mVi, &bits);
    389                     if (ret != 0) {
    390                         notify(OMX_EventError, OMX_ErrorUndefined, ret, NULL);
    391                         mSignalledError = true;
    392                         return;
    393                     }
    394                 } else {
    395                     int ret = _vorbis_unpack_books(mVi, &bits);
    396                     if (ret != 0) {
    397                         notify(OMX_EventError, OMX_ErrorUndefined, ret, NULL);
    398                         mSignalledError = true;
    399                         return;
    400                     }
    401 
    402                     CHECK(mState == NULL);
    403                     mState = new vorbis_dsp_state;
    404                     CHECK_EQ(0, vorbis_dsp_init(mState, mVi));
    405 
    406                     if (mVi->rate != kDefaultSamplingRate ||
    407                             mVi->channels != kDefaultChannelCount) {
    408                         ALOGV("vorbis: rate/channels changed: %ld/%d", mVi->rate, mVi->channels);
    409                         notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
    410                         mOutputPortSettingsChange = AWAITING_DISABLED;
    411                     }
    412                 }
    413 
    414                 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
    415                     handleEOS();
    416                     return;
    417                 }
    418 
    419                 inQueue.erase(inQueue.begin());
    420                 inInfo->mOwnedByUs = false;
    421                 notifyEmptyBufferDone(inHeader);
    422                 ++mInputBufferCount;
    423 
    424                 continue;
    425             }
    426 
    427             if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
    428                 mSawInputEos = true;
    429             }
    430 
    431             if (inHeader->nFilledLen || !mSawInputEos) {
    432                 if (inHeader->nFilledLen < sizeof(numPageSamples)) {
    433                     notify(OMX_EventError, OMX_ErrorBadParameter, 0, NULL);
    434                     mSignalledError = true;
    435                     ALOGE("onQueueFilled, input header has nFilledLen %u, expected %zu",
    436                             inHeader->nFilledLen, sizeof(numPageSamples));
    437                     return;
    438                 }
    439                 memcpy(&numPageSamples,
    440                        inHeader->pBuffer + inHeader->nOffset + inHeader->nFilledLen - 4,
    441                        sizeof(numPageSamples));
    442 
    443                 if (inHeader->nOffset == 0) {
    444                     mAnchorTimeUs = inHeader->nTimeStamp;
    445                     mNumFramesOutput = 0;
    446                 }
    447 
    448                 inHeader->nFilledLen -= sizeof(numPageSamples);;
    449             }
    450         }
    451 
    452         if (numPageSamples >= 0) {
    453             mNumFramesLeftOnPage = numPageSamples;
    454         }
    455 
    456         ogg_buffer buf;
    457         buf.data = inHeader ? inHeader->pBuffer + inHeader->nOffset : NULL;
    458         buf.size = inHeader ? inHeader->nFilledLen : 0;
    459         buf.refcount = 1;
    460         buf.ptr.owner = NULL;
    461 
    462         ogg_reference ref;
    463         ref.buffer = &buf;
    464         ref.begin = 0;
    465         ref.length = buf.size;
    466         ref.next = NULL;
    467 
    468         ogg_packet pack;
    469         pack.packet = &ref;
    470         pack.bytes = ref.length;
    471         pack.b_o_s = 0;
    472         pack.e_o_s = 0;
    473         pack.granulepos = 0;
    474         pack.packetno = 0;
    475 
    476         int numFrames = 0;
    477 
    478         outHeader->nFlags = 0;
    479 
    480         if (mState == nullptr || mVi == nullptr) {
    481             notify(OMX_EventError, OMX_ErrorStreamCorrupt, 0, NULL);
    482             mSignalledError = true;
    483             ALOGE("onQueueFilled, input does not have CSD");
    484             return;
    485         }
    486 
    487         int err = vorbis_dsp_synthesis(mState, &pack, 1);
    488         if (err != 0) {
    489             // FIXME temporary workaround for log spam
    490 #if !defined(__arm__) && !defined(__aarch64__)
    491             ALOGV("vorbis_dsp_synthesis returned %d", err);
    492 #else
    493             ALOGW("vorbis_dsp_synthesis returned %d", err);
    494 #endif
    495         } else {
    496             size_t numSamplesPerBuffer = kMaxNumSamplesPerBuffer;
    497             if (numSamplesPerBuffer > outHeader->nAllocLen / sizeof(int16_t)) {
    498                 numSamplesPerBuffer = outHeader->nAllocLen / sizeof(int16_t);
    499                 android_errorWriteLog(0x534e4554, "27833616");
    500             }
    501             numFrames = vorbis_dsp_pcmout(
    502                     mState, (int16_t *)outHeader->pBuffer,
    503                     (numSamplesPerBuffer / mVi->channels));
    504 
    505             if (numFrames < 0) {
    506                 ALOGE("vorbis_dsp_pcmout returned %d", numFrames);
    507                 numFrames = 0;
    508             }
    509         }
    510 
    511         if (mNumFramesLeftOnPage >= 0) {
    512             if (numFrames > mNumFramesLeftOnPage) {
    513                 ALOGV("discarding %d frames at end of page",
    514                      numFrames - mNumFramesLeftOnPage);
    515                 numFrames = mNumFramesLeftOnPage;
    516                 if (mSawInputEos) {
    517                     outHeader->nFlags = OMX_BUFFERFLAG_EOS;
    518                     mSignalledOutputEos = true;
    519                 }
    520             }
    521             mNumFramesLeftOnPage -= numFrames;
    522         }
    523 
    524         outHeader->nFilledLen = numFrames * sizeof(int16_t) * mVi->channels;
    525         outHeader->nOffset = 0;
    526 
    527         outHeader->nTimeStamp =
    528             mAnchorTimeUs
    529                 + (mNumFramesOutput * 1000000ll) / mVi->rate;
    530 
    531         mNumFramesOutput += numFrames;
    532 
    533         if (inHeader) {
    534             inInfo->mOwnedByUs = false;
    535             inQueue.erase(inQueue.begin());
    536             notifyEmptyBufferDone(inHeader);
    537             ++mInputBufferCount;
    538         }
    539 
    540         outInfo->mOwnedByUs = false;
    541         outQueue.erase(outQueue.begin());
    542         notifyFillBufferDone(outHeader);
    543     }
    544 }
    545 
    546 void SoftVorbis::onPortFlushCompleted(OMX_U32 portIndex) {
    547     if (portIndex == 0 && mState != NULL) {
    548         // Make sure that the next buffer output does not still
    549         // depend on fragments from the last one decoded.
    550 
    551         mNumFramesOutput = 0;
    552         mSawInputEos = false;
    553         mSignalledOutputEos = false;
    554         mNumFramesLeftOnPage = -1;
    555         vorbis_dsp_restart(mState);
    556     }
    557 }
    558 
    559 void SoftVorbis::onReset() {
    560     mInputBufferCount = 0;
    561     mNumFramesOutput = 0;
    562     if (mState != NULL) {
    563         vorbis_dsp_clear(mState);
    564         delete mState;
    565         mState = NULL;
    566     }
    567 
    568     if (mVi != NULL) {
    569         vorbis_info_clear(mVi);
    570         delete mVi;
    571         mVi = NULL;
    572     }
    573 
    574     mSawInputEos = false;
    575     mSignalledOutputEos = false;
    576     mSignalledError = false;
    577     mOutputPortSettingsChange = NONE;
    578 }
    579 
    580 void SoftVorbis::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
    581     if (portIndex != 1) {
    582         return;
    583     }
    584 
    585     switch (mOutputPortSettingsChange) {
    586         case NONE:
    587             break;
    588 
    589         case AWAITING_DISABLED:
    590         {
    591             CHECK(!enabled);
    592             mOutputPortSettingsChange = AWAITING_ENABLED;
    593             break;
    594         }
    595 
    596         default:
    597         {
    598             CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
    599             CHECK(enabled);
    600             mOutputPortSettingsChange = NONE;
    601             break;
    602         }
    603     }
    604 }
    605 
    606 }  // namespace android
    607 
    608 android::SoftOMXComponent *createSoftOMXComponent(
    609         const char *name, const OMX_CALLBACKTYPE *callbacks,
    610         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
    611     return new android::SoftVorbis(name, callbacks, appData, component);
    612 }
    613