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

Commit 6ec0f94d authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "Optionally emit LPCM audio instead of using AAC in wifi display code" into jb-mr1-dev

parents ef7fdc22 20a5a986
Loading
Loading
Loading
Loading
+145 −9
Original line number Diff line number Diff line
@@ -38,12 +38,14 @@ namespace android {
Converter::Converter(
        const sp<AMessage> &notify,
        const sp<ALooper> &codecLooper,
        const sp<AMessage> &format)
        const sp<AMessage> &format,
        bool usePCMAudio)
    : mInitCheck(NO_INIT),
      mNotify(notify),
      mCodecLooper(codecLooper),
      mInputFormat(format),
      mIsVideo(false),
      mIsPCMAudio(usePCMAudio),
      mDoMoreWorkPending(false)
#if ENABLE_SILENCE_DETECTION
      ,mFirstSilentFrameUs(-1ll)
@@ -57,6 +59,8 @@ Converter::Converter(
        mIsVideo = true;
    }

    CHECK(!usePCMAudio || !mIsVideo);

    mInitCheck = initEncoder();

    if (mInitCheck != OK) {
@@ -109,7 +113,11 @@ status_t Converter::initEncoder() {
    AString outputMIME;
    bool isAudio = false;
    if (!strcasecmp(inputMIME.c_str(), MEDIA_MIMETYPE_AUDIO_RAW)) {
        if (mIsPCMAudio) {
            outputMIME = MEDIA_MIMETYPE_AUDIO_RAW;
        } else {
            outputMIME = MEDIA_MIMETYPE_AUDIO_AAC;
        }
        isAudio = true;
    } else if (!strcasecmp(inputMIME.c_str(), MEDIA_MIMETYPE_VIDEO_RAW)) {
        outputMIME = MEDIA_MIMETYPE_VIDEO_AVC;
@@ -117,14 +125,21 @@ status_t Converter::initEncoder() {
        TRESPASS();
    }

    if (!mIsPCMAudio) {
        mEncoder = MediaCodec::CreateByType(
                mCodecLooper, outputMIME.c_str(), true /* encoder */);

        if (mEncoder == NULL) {
            return ERROR_UNSUPPORTED;
        }
    }

    mOutputFormat = mInputFormat->dup();

    if (mIsPCMAudio) {
        return OK;
    }

    mOutputFormat->setString("mime", outputMIME.c_str());

    int32_t audioBitrate = getBitrate("media.wfd.audio-bitrate", 128000);
@@ -197,7 +212,7 @@ void Converter::onMessageReceived(const sp<AMessage> &msg) {
            int32_t what;
            CHECK(msg->findInt32("what", &what));

            if (mEncoder == NULL) {
            if (!mIsPCMAudio && mEncoder == NULL) {
                ALOGV("got msg '%s' after encoder shutdown.",
                      msg->debugString().c_str());

@@ -317,8 +332,11 @@ void Converter::onMessageReceived(const sp<AMessage> &msg) {
        case kWhatShutdown:
        {
            ALOGI("shutting down encoder");

            if (mEncoder != NULL) {
                mEncoder->release();
                mEncoder.clear();
            }

            AString mime;
            CHECK(mInputFormat->findString("mime", &mime));
@@ -332,6 +350,11 @@ void Converter::onMessageReceived(const sp<AMessage> &msg) {
}

void Converter::scheduleDoMoreWork() {
    if (mIsPCMAudio) {
        // There's no encoder involved in this case.
        return;
    }

    if (mDoMoreWorkPending) {
        return;
    }
@@ -350,7 +373,120 @@ void Converter::scheduleDoMoreWork() {
#endif
}

status_t Converter::feedRawAudioInputBuffers() {
    // Split incoming PCM audio into buffers of 6 AUs of 80 audio frames each
    // and add a 4 byte header according to the wifi display specs.

    while (!mInputBufferQueue.empty()) {
        sp<ABuffer> buffer = *mInputBufferQueue.begin();
        mInputBufferQueue.erase(mInputBufferQueue.begin());

        int16_t *ptr = (int16_t *)buffer->data();
        int16_t *stop = (int16_t *)(buffer->data() + buffer->size());
        while (ptr < stop) {
            *ptr = htons(*ptr);
            ++ptr;
        }

        static const size_t kFrameSize = 2 * sizeof(int16_t);  // stereo
        static const size_t kFramesPerAU = 80;
        static const size_t kNumAUsPerPESPacket = 6;

        if (mPartialAudioAU != NULL) {
            size_t bytesMissingForFullAU =
                kNumAUsPerPESPacket * kFramesPerAU * kFrameSize
                - mPartialAudioAU->size() + 4;

            size_t copy = buffer->size();
            if(copy > bytesMissingForFullAU) {
                copy = bytesMissingForFullAU;
            }

            memcpy(mPartialAudioAU->data() + mPartialAudioAU->size(),
                   buffer->data(),
                   copy);

            mPartialAudioAU->setRange(0, mPartialAudioAU->size() + copy);

            buffer->setRange(buffer->offset() + copy, buffer->size() - copy);

            int64_t timeUs;
            CHECK(buffer->meta()->findInt64("timeUs", &timeUs));

            int64_t copyUs = (int64_t)((copy / kFrameSize) * 1E6 / 48000.0);
            timeUs += copyUs;
            buffer->meta()->setInt64("timeUs", timeUs);

            if (bytesMissingForFullAU == copy) {
                sp<AMessage> notify = mNotify->dup();
                notify->setInt32("what", kWhatAccessUnit);
                notify->setBuffer("accessUnit", mPartialAudioAU);
                notify->post();

                mPartialAudioAU.clear();
            }
        }

        while (buffer->size() > 0) {
            sp<ABuffer> partialAudioAU =
                new ABuffer(
                        4
                        + kNumAUsPerPESPacket * kFrameSize * kFramesPerAU);

            uint8_t *ptr = partialAudioAU->data();
            ptr[0] = 0xa0;  // 10100000b
            ptr[1] = kNumAUsPerPESPacket;
            ptr[2] = 0;  // reserved, audio _emphasis_flag = 0

            static const unsigned kQuantizationWordLength = 0;  // 16-bit
            static const unsigned kAudioSamplingFrequency = 2;  // 48Khz
            static const unsigned kNumberOfAudioChannels = 1;  // stereo

            ptr[3] = (kQuantizationWordLength << 6)
                    | (kAudioSamplingFrequency << 3)
                    | kNumberOfAudioChannels;

            size_t copy = buffer->size();
            if (copy > partialAudioAU->size() - 4) {
                copy = partialAudioAU->size() - 4;
            }

            memcpy(&ptr[4], buffer->data(), copy);

            partialAudioAU->setRange(0, 4 + copy);
            buffer->setRange(buffer->offset() + copy, buffer->size() - copy);

            int64_t timeUs;
            CHECK(buffer->meta()->findInt64("timeUs", &timeUs));

            partialAudioAU->meta()->setInt64("timeUs", timeUs);

            int64_t copyUs = (int64_t)((copy / kFrameSize) * 1E6 / 48000.0);
            timeUs += copyUs;
            buffer->meta()->setInt64("timeUs", timeUs);

            if (copy == partialAudioAU->size() - 4) {
                sp<AMessage> notify = mNotify->dup();
                notify->setInt32("what", kWhatAccessUnit);
                notify->setBuffer("accessUnit", partialAudioAU);
                notify->post();

                partialAudioAU.clear();
                continue;
            }

            mPartialAudioAU = partialAudioAU;
        }
    }

    return OK;
}

status_t Converter::feedEncoderInputBuffers() {
    if (mIsPCMAudio) {
        return feedRawAudioInputBuffers();
    }

    while (!mInputBufferQueue.empty()
            && !mAvailEncoderInputIndices.empty()) {
        sp<ABuffer> buffer = *mInputBufferQueue.begin();
+12 −1
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@

#define CONVERTER_H_

#include "WifiDisplaySource.h"

#include <media/stagefright/foundation/AHandler.h>

namespace android {
@@ -34,7 +36,8 @@ struct Converter : public AHandler {
    Converter(
            const sp<AMessage> &notify,
            const sp<ALooper> &codecLooper,
            const sp<AMessage> &format);
            const sp<AMessage> &format,
            bool usePCMAudio);

    status_t initCheck() const;

@@ -73,6 +76,7 @@ private:
    sp<ALooper> mCodecLooper;
    sp<AMessage> mInputFormat;
    bool mIsVideo;
    bool mIsPCMAudio;
    sp<AMessage> mOutputFormat;

    sp<MediaCodec> mEncoder;
@@ -92,6 +96,8 @@ private:
    bool mInSilentMode;
#endif

    sp<ABuffer> mPartialAudioAU;

    status_t initEncoder();

    status_t feedEncoderInputBuffers();
@@ -101,6 +107,11 @@ private:

    void notifyError(status_t err);

    // Packetizes raw PCM audio data available in mInputBufferQueue
    // into a format suitable for transport stream inclusion and
    // notifies the observer.
    status_t feedRawAudioInputBuffers();

    static bool IsSilence(const sp<ABuffer> &accessUnit);

    DISALLOW_EVIL_CONSTRUCTORS(Converter);
+14 −10
Original line number Diff line number Diff line
@@ -312,10 +312,11 @@ WifiDisplaySource::PlaybackSession::PlaybackSession(

status_t WifiDisplaySource::PlaybackSession::init(
        const char *clientIP, int32_t clientRtp, int32_t clientRtcp,
        TransportMode transportMode) {
        TransportMode transportMode,
        bool usePCMAudio) {
    mClientIP = clientIP;

    status_t err = setupPacketizer();
    status_t err = setupPacketizer(usePCMAudio);

    if (err != OK) {
        return err;
@@ -823,7 +824,7 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
    }
}

status_t WifiDisplaySource::PlaybackSession::setupPacketizer() {
status_t WifiDisplaySource::PlaybackSession::setupPacketizer(bool usePCMAudio) {
    mPacketizer = new TSPacketizer;

    status_t err = addVideoSource();
@@ -832,12 +833,15 @@ status_t WifiDisplaySource::PlaybackSession::setupPacketizer() {
        return err;
    }

    return addAudioSource();
    return addAudioSource(usePCMAudio);
}

status_t WifiDisplaySource::PlaybackSession::addSource(
        bool isVideo, const sp<MediaSource> &source, bool isRepeaterSource,
        size_t *numInputBuffers) {
        bool usePCMAudio, size_t *numInputBuffers) {
    CHECK(!usePCMAudio || !isVideo);
    CHECK(!isRepeaterSource || isVideo);

    sp<ALooper> pullLooper = new ALooper;
    pullLooper->setName("pull_looper");

@@ -875,7 +879,7 @@ status_t WifiDisplaySource::PlaybackSession::addSource(
    notify->setSize("trackIndex", trackIndex);

    sp<Converter> converter =
        new Converter(notify, codecLooper, format);
        new Converter(notify, codecLooper, format, usePCMAudio);

    if (converter->initCheck() != OK) {
        return converter->initCheck();
@@ -928,12 +932,12 @@ status_t WifiDisplaySource::PlaybackSession::addVideoSource() {
    size_t numInputBuffers;
    status_t err = addSource(
            true /* isVideo */, videoSource, true /* isRepeaterSource */,
            &numInputBuffers);
            false /* usePCMAudio */, &numInputBuffers);
#else
    size_t numInputBuffers;
    status_t err = addSource(
            true /* isVideo */, source, false /* isRepeaterSource */,
            &numInputBuffers);
            false /* usePCMAudio */, &numInputBuffers);
#endif

    if (err != OK) {
@@ -948,7 +952,7 @@ status_t WifiDisplaySource::PlaybackSession::addVideoSource() {
    return OK;
}

status_t WifiDisplaySource::PlaybackSession::addAudioSource() {
status_t WifiDisplaySource::PlaybackSession::addAudioSource(bool usePCMAudio) {
    sp<AudioSource> audioSource = new AudioSource(
            AUDIO_SOURCE_REMOTE_SUBMIX,
            48000 /* sampleRate */,
@@ -957,7 +961,7 @@ status_t WifiDisplaySource::PlaybackSession::addAudioSource() {
    if (audioSource->initCheck() == OK) {
        return addSource(
                false /* isVideo */, audioSource, false /* isRepeaterSource */,
                NULL /* numInputBuffers */);
                usePCMAudio, NULL /* numInputBuffers */);
    }

    ALOGW("Unable to instantiate audio source");
+5 −3
Original line number Diff line number Diff line
@@ -50,7 +50,8 @@ struct WifiDisplaySource::PlaybackSession : public AHandler {
    };
    status_t init(
            const char *clientIP, int32_t clientRtp, int32_t clientRtcp,
            TransportMode transportMode);
            TransportMode transportMode,
            bool usePCMAudio);

    void destroyAsync();

@@ -180,16 +181,17 @@ private:
    void addSDES(const sp<ABuffer> &buffer);
    static uint64_t GetNowNTP();

    status_t setupPacketizer();
    status_t setupPacketizer(bool usePCMAudio);

    status_t addSource(
            bool isVideo,
            const sp<MediaSource> &source,
            bool isRepeaterSource,
            bool usePCMAudio,
            size_t *numInputBuffers);

    status_t addVideoSource();
    status_t addAudioSource();
    status_t addAudioSource(bool usePCMAudio);

    ssize_t appendTSData(
            const void *data, size_t size, bool timeDiscontinuity, bool flush);
+10 −1
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ struct TSPacketizer::Track : public RefBase {
    bool isVideo() const;

    bool isH264() const;
    bool isAAC() const;
    bool lacksADTSHeader() const;

    sp<ABuffer> prependCSD(const sp<ABuffer> &accessUnit) const;
@@ -139,6 +140,10 @@ bool TSPacketizer::Track::isH264() const {
    return !strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_VIDEO_AVC);
}

bool TSPacketizer::Track::isAAC() const {
    return !strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_AUDIO_AAC);
}

bool TSPacketizer::Track::lacksADTSHeader() const {
    return mAudioLacksATDSHeaders;
}
@@ -247,6 +252,10 @@ ssize_t TSPacketizer::addTrack(const sp<AMessage> &format) {
        streamType = 0x0f;
        streamIDStart = 0xc0;
        streamIDStop = 0xdf;
    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_RAW)) {
        streamType = 0x83;
        streamIDStart = 0xbd;
        streamIDStop = 0xbd;
    } else {
        return ERROR_UNSUPPORTED;
    }
@@ -298,7 +307,7 @@ status_t TSPacketizer::packetize(
            && IsIDR(accessUnit)) {
        // prepend codec specific data, i.e. SPS and PPS.
        accessUnit = track->prependCSD(accessUnit);
    } else if (track->isAudio() && track->lacksADTSHeader()) {
    } else if (track->isAAC() && track->lacksADTSHeader()) {
        CHECK(!(flags & IS_ENCRYPTED));
        accessUnit = track->prependADTSHeader(accessUnit);
    }
Loading