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

Commit 7daf0353 authored by Steve Kondik's avatar Steve Kondik
Browse files

nuplayer: Fixes for PCM offload

 * Bring us more in line with upstream.
 * This code modifies NuPlayer to be less error-driven when
   invoking PCM offload.
 * Small bufs feature is currently disabled in this patch, as
   the 8974 DSP does not handle it correctly.

Change-Id: I35ce0d9e55baf0c871d03a5456b47309c34350d4
parent aac30c95
Loading
Loading
Loading
Loading
+58 −36
Original line number Diff line number Diff line
@@ -161,6 +161,7 @@ NuPlayer::NuPlayer()
      mSourceFlags(0),
      mVideoIsAVC(false),
      mOffloadAudio(false),
      mOffloadDecodedPCM(false),
      mIsStreaming(true),
      mAudioDecoderGeneration(0),
      mVideoDecoderGeneration(0),
@@ -615,6 +616,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {

            mVideoIsAVC = false;
            mOffloadAudio = false;
            mOffloadDecodedPCM = false;
            mAudioEOS = false;
            mVideoEOS = false;
            mSkipRenderingAudioUntilMediaTimeUs = -1;
@@ -634,7 +636,11 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
                }
            }

            sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
            if (!(ExtendedUtils::isRAWFormat(audioMeta) &&
                        ExtendedUtils::isPcmOffloadEnabled())) {
                mSource->start();
            }

            uint32_t flags = 0;

@@ -642,7 +648,6 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
                flags |= Renderer::FLAG_REAL_TIME;
            }

            sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
            audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
            if (mAudioSink != NULL) {
                streamType = mAudioSink->getAudioStreamType();
@@ -655,6 +660,18 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
            mOffloadAudio =
                canOffloadStream(audioMeta, (videoFormat != NULL), vMeta,
                                 mIsStreaming /* is_streaming */, streamType);

#ifdef ENABLE_AV_ENHANCEMENTS
            if (!mOffloadAudio && ExtendedUtils::isPcmOffloadEnabled() && audioMeta != NULL) {
                sp<MetaData> pcmMeta = ExtendedUtils::createPCMMetaFromSource(audioMeta);
                mOffloadAudio = 
                    canOffloadStream(pcmMeta, (videoFormat != NULL), vMeta,
                                     mIsStreaming /* is_streaming */, streamType);
                mOffloadDecodedPCM = mOffloadAudio;
                ALOGV("Could not offload audio decode, pcm offload decided %d", mOffloadDecodedPCM);
            }
#endif

            if (mOffloadAudio) {
                flags |= Renderer::FLAG_OFFLOAD_AUDIO;
            }
@@ -964,18 +981,24 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
                int32_t reason;
                CHECK(msg->findInt32("reason", &reason));
                closeAudioSink();
                mRenderer->flush(true /* audio */);
                mAudioDecoder.clear();
                ++mAudioDecoderGeneration;
                mRenderer->flush(true /* audio */);
                if (mVideoDecoder != NULL) {
                    mRenderer->flush(false /* audio */);
                }

                performSeek(positionUs, false /* needNotify */);
                if (reason == Renderer::kDueToError) {
                    ALOGV("teardown due to error, retry");
                    mRenderer->signalDisableOffloadAudio();
                    mOffloadAudio = false;
                    mOffloadDecodedPCM = false;
                    instantiateDecoder(true /* audio */, &mAudioDecoder);
                    sp<MetaData> audioMeta = mSource->getFormatMeta(true);
                    if (ExtendedUtils::isRAWFormat(audioMeta) &&
                            ExtendedUtils::isPcmOffloadEnabled()) {
                        mSource->start();
                    }
                }
            }
            break;
@@ -1173,6 +1196,8 @@ void NuPlayer::postScanSources() {
void NuPlayer::openAudioSink(const sp<AMessage> &format, bool offloadOnly) {
    uint32_t flags;
    int64_t durationUs;
    bool hasVideo = (mVideoDecoder != NULL);

    if (mSource->getDuration(&durationUs) == OK &&
            durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
        flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
@@ -1180,39 +1205,27 @@ void NuPlayer::openAudioSink(const sp<AMessage> &format, bool offloadOnly) {
        flags = AUDIO_OUTPUT_FLAG_NONE;
    }

    format->setInt64("durationUs", durationUs);

    // avoid PCM offload when resampler is used
    bool resampled = false;
    sp<MetaData> audioMeta = mSource->getFormatMeta(true);

    AString mime;
    CHECK(format->findString("mime", &mime));
    if (audioMeta != NULL && !strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_RAW)) {
        int32_t srcBitsPerSample, bitsPerSample = 16;
        int32_t srcChannels, channels = 0;
        int32_t srcSampleRate, sampleRate = 0;
        audioMeta->findInt32(kKeyBitsPerSample, &srcBitsPerSample);
        format->findInt32("bits-per-sample", &bitsPerSample);
        audioMeta->findInt32(kKeyChannelCount, &srcChannels);
        format->findInt32("channel-count", &channels);
        audioMeta->findInt32(kKeySampleRate, &srcSampleRate);
        format->findInt32("sample-rate", &sampleRate);
    sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);

        resampled = !((srcBitsPerSample == bitsPerSample) &&
                      (srcChannels == channels) &&
                      (srcSampleRate == sampleRate));
        format->setInt32("resampled", resampled);
#ifdef ENABLE_AV_ENHANCEMENTS
    if (mOffloadDecodedPCM && audioMeta != NULL) {
        sp<MetaData> audioPCMMeta = ExtendedUtils::createPCMMetaFromSource(audioMeta);
        sp<AMessage> msg = new AMessage;
        if (convertMetaDataToMessage(audioPCMMeta, &msg) == OK) {
            //override msg with value in format if format has updated values
            ExtendedUtils::overWriteAudioFormat(msg, format);
            mOffloadAudio = mRenderer->openAudioSink(
                    msg, offloadOnly, hasVideo, flags);
        } else {
            mOffloadAudio = mRenderer->openAudioSink(
                    format, offloadOnly, hasVideo, flags);
        }

    ALOGV("openAudioSink: resampled=%d format=%s", resampled, format->debugString().c_str());

    } else
#endif
        mOffloadAudio = mRenderer->openAudioSink(
            format, offloadOnly, (mVideoDecoder != NULL), flags);
                format, offloadOnly, hasVideo, flags);

    if (mOffloadAudio) {
        sp<MetaData> audioMeta =
                mSource->getFormatMeta(true /* audio */);
        sendMetaDataToHal(mAudioSink, audioMeta);
    }
}
@@ -1254,9 +1267,18 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
        ++mAudioDecoderGeneration;
        notify->setInt32("generation", mAudioDecoderGeneration);

        if (mOffloadAudio) {
        sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
        if (mOffloadAudio && !mOffloadDecodedPCM) {
            if (ExtendedUtils::isRAWFormat(audioMeta) &&
                        ExtendedUtils::isPcmOffloadEnabled()) {
                mSource->start();
            }
            *decoder = new DecoderPassThrough(notify);
        } else {
            if (ExtendedUtils::isRAWFormat(audioMeta) &&
                        ExtendedUtils::isPcmOffloadEnabled()) {
                mSource->start();
            }
            *decoder = new Decoder(notify);
        }
    } else {
@@ -1316,7 +1338,7 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
    // Aggregate smaller buffers into a larger buffer.
    // The goal is to reduce power consumption.
    // Note this will not work if the decoder requires one frame per buffer.
    bool doBufferAggregation = (audio && mOffloadAudio);
    bool doBufferAggregation = ((audio && mOffloadAudio) && !mOffloadDecodedPCM);
    bool needMoreData = false;

    bool dropAccessUnit;
+1 −0
Original line number Diff line number Diff line
@@ -144,6 +144,7 @@ private:
    sp<Decoder> mVideoDecoder;
    bool mVideoIsAVC;
    bool mOffloadAudio;
    bool mOffloadDecodedPCM;
    bool mIsStreaming;
    sp<Decoder> mAudioDecoder;
    sp<CCDecoder> mCCDecoder;
+6 −20
Original line number Diff line number Diff line
@@ -1379,7 +1379,6 @@ bool NuPlayer::Renderer::onOpenAudioSink(
    ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
            offloadOnly, offloadingAudio());
    bool audioSinkChanged = false;
    bool pcmOffload = false;

    int32_t numChannels;
    CHECK(format->findInt32("channel-count", &numChannels));
@@ -1399,24 +1398,6 @@ bool NuPlayer::Renderer::onOpenAudioSink(
    AString mime;
    CHECK(format->findString("mime", &mime));

#ifdef ENABLE_AV_ENHANCEMENTS
    pcmOffload = ExtendedUtils::isPcmOffloadEnabled() &&
            !strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_RAW);

    int32_t resampled = 0;
    format->findInt32("resampled", &resampled);

    // At this point we can check if PCM should be offloaded
    if (!offloadingAudio() && (!offloadOnly && pcmOffload && !resampled)) {
        sp<MetaData> aMeta = new MetaData;
        convertMessageToMetaData(format, aMeta);
        if  (canOffloadStream(aMeta, false, new MetaData,
                    hasVideo, AUDIO_STREAM_MUSIC)) {
            mFlags |= FLAG_OFFLOAD_AUDIO;
        }
    }
#endif

    if (offloadingAudio()) {
        audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
        status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str());
@@ -1426,8 +1407,10 @@ bool NuPlayer::Renderer::onOpenAudioSink(
                    "audio_format", mime.c_str());
            onDisableOffloadAudio();
        } else {

#ifdef ENABLE_AV_ENHANCEMENTS
            if (pcmOffload) {
            if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_RAW) &&
                    ExtendedUtils::isPcmOffloadEnabled()) {
                if (bitsPerSample > 16) {
                    audioFormat = AUDIO_FORMAT_PCM_24_BIT_OFFLOAD;
                } else {
@@ -1462,6 +1445,9 @@ bool NuPlayer::Renderer::onOpenAudioSink(
            offloadInfo.has_video = hasVideo;
            offloadInfo.is_streaming = true;
            offloadInfo.bit_width = bitsPerSample;
#ifdef ENABLE_AV_ENHANCEMENTS
            //offloadInfo.use_small_bufs = (audioFormat == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD);
#endif

            if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
                ALOGV("openAudioSink: no change in offload mode");
+141 −1
Original line number Diff line number Diff line
@@ -951,6 +951,29 @@ bool ExtendedUtils::UseQCHWAACEncoder(audio_encoder Encoder,int32_t Channel,int3
    return mIsQCHWAACEncoder;
}

bool ExtendedUtils::isRAWFormat(const sp<MetaData> &meta) {
    const char *mime = {0};
    if (meta == NULL) {
        return false;
    }
    CHECK(meta->findCString(kKeyMIMEType, &mime));
    if (!strncasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW, 9))
        return true;
    else
        return false;
}

bool ExtendedUtils::isRAWFormat(const sp<AMessage> &format) {
    AString mime;
    if (format == NULL) {
        return false;
    }
    CHECK(format->findString("mime", &mime));
    if (!strncasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_RAW, 9))
        return true;
    else
        return false;
}

//- returns NULL if we dont really need a new extractor (or cannot),
//  valid extractor is returned otherwise
@@ -989,9 +1012,9 @@ sp<MediaExtractor> ExtendedUtils::MediaExtractor_CreateIfNeeded(sp<MediaExtracto
            String8 mime = String8(_mime);

            const char * dolbyFormats[ ] = {
#ifdef DOLBY_UDC
                MEDIA_MIMETYPE_AUDIO_AC3,
                MEDIA_MIMETYPE_AUDIO_EAC3,
#ifdef DOLBY_UDC
                MEDIA_MIMETYPE_AUDIO_EAC3_JOC,
#endif
            };
@@ -1746,6 +1769,98 @@ bool ExtendedUtils::pcmOffloadException(const char* const mime) {
    return decision;
}

sp<MetaData> ExtendedUtils::createPCMMetaFromSource(
                const sp<MetaData> &sMeta)
{

    sp<MetaData> tPCMMeta = new MetaData;
    //hard code as RAW
    tPCMMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);

    int32_t bitsPerSample = 16;
    if (!sMeta->findInt32(kKeyBitsPerSample, &bitsPerSample)) {
        ALOGI("Bits per sample not set, default to 16");
    }
    tPCMMeta->setInt32(kKeyBitsPerSample, bitsPerSample);

    int32_t srate = -1;
    if (!sMeta->findInt32(kKeySampleRate, &srate)) {
        ALOGV("No sample rate");
    }
    tPCMMeta->setInt32(kKeySampleRate, srate);

    int32_t cmask = 0;
    if (!sMeta->findInt32(kKeyChannelMask, &cmask) || (cmask == 0)) {
        ALOGI("No channel mask, try channel count");
    }
    int32_t channelCount = 0;
    if (!sMeta->findInt32(kKeyChannelCount, &channelCount)) {
        ALOGI("No channel count either");
    } else {
        //if channel mask is not set till now, use channel count
        //to retrieve channel count
        if (!cmask) {
            cmask = audio_channel_out_mask_from_count(channelCount);
        }
    }
    tPCMMeta->setInt32(kKeyChannelCount, channelCount);
    tPCMMeta->setInt32(kKeyChannelMask, cmask);

    int64_t duration = 0;
    if (!sMeta->findInt64(kKeyDuration, &duration)) {
        ALOGW("No duration in meta");
    } else {
        tPCMMeta->setInt64(kKeyDuration, duration);
    }

    int32_t bitRate = -1;
    if (!sMeta->findInt32(kKeyBitRate, &bitRate)) {
        ALOGW("No bitrate info");
    } else {
        tPCMMeta->setInt32(kKeyBitRate, bitRate);
    }

    return tPCMMeta;
}

void ExtendedUtils::overWriteAudioFormat(
                sp<AMessage> &dst, const sp<AMessage> &src)
{
    int32_t dchannels = 0;
    int32_t schannels = 0;
    int32_t drate = 0;
    int32_t srate = 0;
    int32_t dbits = 16;
    int32_t sbits = 16;

    dst->findInt32("channel-count", &dchannels);
    src->findInt32("channel-count", &schannels);

    dst->findInt32("sample-rate", &drate);
    src->findInt32("sample-rate", &srate);

    dst->findInt32("bits-per-sample", &dbits);
    src->findInt32("bits-per-sample", &sbits);

    ALOGV("channel count src: %d dst: %d", dchannels, schannels);
    ALOGV("sample rate src: %d dst:%d ", drate, srate);
    ALOGV("bits per sample src: %d dst: %d", dbits, sbits);

    if (schannels && dchannels != schannels) {
        dst->setInt32("channel-count", schannels);
    }

    if (srate && drate != srate) {
        dst->setInt32("sample-rate", srate);
    }

    if (sbits && dbits != sbits) {
        dst->setInt32("bits-per-sample", sbits);
    }

    return;
}

void ExtendedUtils::detectAndPostImage(const sp<ABuffer> accessUnit,
        const sp<AMessage> &notify) {
    if (accessUnit == NULL || notify == NULL)
@@ -2038,6 +2153,16 @@ bool ExtendedUtils::UseQCHWAACEncoder(audio_encoder Encoder,int32_t Channel,
    return false;
}

bool ExtendedUtils::isRAWFormat(const sp<MetaData> &meta) {
    ARG_TOUCH(meta);
    return false;
}

bool ExtendedUtils::isRAWFormat(const sp<AMessage> &format) {
    ARG_TOUCH(format);
    return false;
}

sp<MediaExtractor> ExtendedUtils::MediaExtractor_CreateIfNeeded(
        sp<MediaExtractor> defaultExt,
        const sp<DataSource> &source,
@@ -2187,6 +2312,21 @@ bool ExtendedUtils::pcmOffloadException(const char* const mime) {
    return true;
}

sp<MetaData> ExtendedUtils::createPCMMetaFromSource(
                const sp<MetaData> &sMeta) {
    ARG_TOUCH(sMeta);
    sp<MetaData> tPCMMeta = new MetaData;
    return tPCMMeta;
}

void ExtendedUtils::overWriteAudioFormat(
                sp<AMessage> &dst, const sp<AMessage> &src)
{
    ARG_TOUCH(dst);
    ARG_TOUCH(src);
    return;
}

} // namespace android
#endif //ENABLE_AV_ENHANCEMENTS

+9 −0
Original line number Diff line number Diff line
@@ -214,6 +214,9 @@ struct ExtendedUtils {
    static bool UseQCHWAACEncoder(audio_encoder Encoder = AUDIO_ENCODER_DEFAULT, int32_t Channel = 0,
            int32_t BitRate = 0, int32_t SampleRate = 0);

    static bool isRAWFormat(const sp<MetaData> &meta);
    static bool isRAWFormat(const sp<AMessage> &format);

    static sp<MediaExtractor> MediaExtractor_CreateIfNeeded(
            sp<MediaExtractor> defaultExt, const sp<DataSource> &source,
            const char *mime);
@@ -246,6 +249,12 @@ struct ExtendedUtils {

    static bool pcmOffloadException(const char* const mime);

    static sp<MetaData> createPCMMetaFromSource(
            const sp<MetaData> &sMeta);

    static void overWriteAudioFormat(
                sp<AMessage> &dst, const sp<AMessage> &src);

    static void detectAndPostImage(const sp<ABuffer> accessunit, const sp<AMessage> &notify);
    static void showImageInNativeWindow(const sp<AMessage> &msg, const sp<AMessage> &format);