Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3e408f39 authored by Andreas Huber's avatar Andreas Huber
Browse files

Support AMR, G.711 and vorbis audio in ACodec and friends.

Change-Id: I08c03219bf2d60fc5c6e89957bd4b4c615570983
parent 9a3d51ed
Loading
Loading
Loading
Loading
+46 −5
Original line number Diff line number Diff line
@@ -46,7 +46,8 @@ struct Controller : public AHandler {
          mDecodeAudio(decodeAudio),
          mSurface(surface),
          mRenderToSurface(renderToSurface),
          mCodec(new ACodec) {
          mCodec(new ACodec),
          mIsVorbis(false) {
        CHECK(!mDecodeAudio || mSurface == NULL);
    }

@@ -85,6 +86,12 @@ protected:
                    if (!strncasecmp(mDecodeAudio ? "audio/" : "video/",
                                     mime, 6)) {
                        mSource = extractor->getTrack(i);

                        if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
                            mIsVorbis = true;
                        } else {
                            mIsVorbis = false;
                        }
                        break;
                    }
                }
@@ -227,6 +234,7 @@ private:
    bool mRenderToSurface;
    sp<ACodec> mCodec;
    sp<MediaSource> mSource;
    bool mIsVorbis;

    Vector<sp<ABuffer> > mCSD;
    size_t mCSDIndex;
@@ -367,6 +375,20 @@ private:
            memcpy(buffer->data(), codec_specific_data,
                   codec_specific_data_size);

            buffer->meta()->setInt32("csd", true);
            mCSD.push(buffer);
        } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
            sp<ABuffer> buffer = new ABuffer(size);
            memcpy(buffer->data(), data, size);

            buffer->meta()->setInt32("csd", true);
            mCSD.push(buffer);

            CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size));

            buffer = new ABuffer(size);
            memcpy(buffer->data(), data, size);

            buffer->meta()->setInt32("csd", true);
            mCSD.push(buffer);
        }
@@ -423,10 +445,17 @@ private:
                    }
                }

                if (inBuffer->range_length() > sizeLeft) {
                size_t sizeNeeded = inBuffer->range_length();
                if (mIsVorbis) {
                    // Vorbis data is suffixed with the number of
                    // valid samples on the page.
                    sizeNeeded += sizeof(int32_t);
                }

                if (sizeNeeded > sizeLeft) {
                    if (outBuffer->size() == 0) {
                        LOGE("Unable to fit even a single input buffer of size %d.",
                             inBuffer->range_length());
                             sizeNeeded);
                    }
                    CHECK_GT(outBuffer->size(), 0u);

@@ -448,10 +477,22 @@ private:
                        + inBuffer->range_offset(),
                       inBuffer->range_length());

                if (mIsVorbis) {
                    int32_t numPageSamples;
                    if (!inBuffer->meta_data()->findInt32(
                                kKeyValidSamples, &numPageSamples)) {
                        numPageSamples = -1;
                    }

                    memcpy(outBuffer->data()
                            + outBuffer->size() + inBuffer->range_length(),
                           &numPageSamples, sizeof(numPageSamples));
                }

                outBuffer->setRange(
                        0, outBuffer->size() + inBuffer->range_length());
                        0, outBuffer->size() + sizeNeeded);

                sizeLeft -= inBuffer->range_length();
                sizeLeft -= sizeNeeded;

                inBuffer->release();
                inBuffer = NULL;
+6 −0
Original line number Diff line number Diff line
@@ -151,6 +151,12 @@ private:
            OMX_VIDEO_CODINGTYPE compressionFormat);

    status_t setupAACDecoder(int32_t numChannels, int32_t sampleRate);
    status_t setupAMRDecoder(bool isWAMR);
    status_t setupG711Decoder(int32_t numChannels);

    status_t setupRawAudioFormat(
            OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels);

    status_t setMinBufferSize(OMX_U32 portIndex, size_t size);

    status_t initNativeWindow();
+93 −3
Original line number Diff line number Diff line
@@ -687,6 +687,8 @@ void ACodec::setComponentRole(
            "audio_decoder.amrwb", "audio_encoder.amrwb" },
        { MEDIA_MIMETYPE_AUDIO_AAC,
            "audio_decoder.aac", "audio_encoder.aac" },
        { MEDIA_MIMETYPE_AUDIO_VORBIS,
            "audio_decoder.vorbis", "audio_encoder.vorbis" },
        { MEDIA_MIMETYPE_VIDEO_AVC,
            "video_decoder.avc", "video_encoder.avc" },
        { MEDIA_MIMETYPE_VIDEO_MPEG4,
@@ -750,9 +752,19 @@ void ACodec::configureCodec(
        CHECK(msg->findInt32("sample-rate", &sampleRate));

        CHECK_EQ(setupAACDecoder(numChannels, sampleRate), (status_t)OK);
    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
    } else {
        TRESPASS();
    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
        CHECK_EQ(setupAMRDecoder(false /* isWAMR */), (status_t)OK);
    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
        CHECK_EQ(setupAMRDecoder(true /* isWAMR */), (status_t)OK);
    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
        // These are PCM-like formats with a fixed sample rate but
        // a variable number of channels.

        int32_t numChannels;
        CHECK(msg->findInt32("channel-count", &numChannels));

        CHECK_EQ(setupG711Decoder(numChannels), (status_t)OK);
    }

    int32_t maxInputSize;
@@ -824,6 +836,84 @@ status_t ACodec::setupAACDecoder(int32_t numChannels, int32_t sampleRate) {
    return err;
}

status_t ACodec::setupAMRDecoder(bool isWAMR) {
    OMX_AUDIO_PARAM_AMRTYPE def;
    InitOMXParams(&def);
    def.nPortIndex = kPortIndexInput;

    status_t err =
        mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));

    if (err != OK) {
        return err;
    }

    def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;

    def.eAMRBandMode =
        isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0;

    return mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
}

status_t ACodec::setupG711Decoder(int32_t numChannels) {
    return setupRawAudioFormat(
            kPortIndexInput, 8000 /* sampleRate */, numChannels);
}

status_t ACodec::setupRawAudioFormat(
        OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
    OMX_PARAM_PORTDEFINITIONTYPE def;
    InitOMXParams(&def);
    def.nPortIndex = portIndex;

    status_t err = mOMX->getParameter(
            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));

    if (err != OK) {
        return err;
    }

    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;

    err = mOMX->setParameter(
            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));

    if (err != OK) {
        return err;
    }

    OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
    InitOMXParams(&pcmParams);
    pcmParams.nPortIndex = portIndex;

    err = mOMX->getParameter(
            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));

    if (err != OK) {
        return err;
    }

    pcmParams.nChannels = numChannels;
    pcmParams.eNumData = OMX_NumericalDataSigned;
    pcmParams.bInterleaved = OMX_TRUE;
    pcmParams.nBitPerSample = 16;
    pcmParams.nSamplingRate = sampleRate;
    pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;

    if (numChannels == 1) {
        pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
    } else {
        CHECK_EQ(numChannels, 2);

        pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
        pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
    }

    return mOMX->setParameter(
            mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
}

status_t ACodec::setVideoPortFormatType(
        OMX_U32 portIndex,
        OMX_VIDEO_CODINGTYPE compressionFormat,
+2 −0
Original line number Diff line number Diff line
@@ -1485,6 +1485,8 @@ void OMXCodec::setComponentRole(
            "audio_decoder.amrwb", "audio_encoder.amrwb" },
        { MEDIA_MIMETYPE_AUDIO_AAC,
            "audio_decoder.aac", "audio_encoder.aac" },
        { MEDIA_MIMETYPE_AUDIO_VORBIS,
            "audio_decoder.vorbis", "audio_encoder.vorbis" },
        { MEDIA_MIMETYPE_VIDEO_AVC,
            "video_decoder.avc", "video_encoder.avc" },
        { MEDIA_MIMETYPE_VIDEO_MPEG4,