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

Commit 87603c0d authored by Lajos Molnar's avatar Lajos Molnar
Browse files

NuPlayer: remember and resubmit CSDs after flush

Bug: 17118001
Change-Id: I09bbefd4c05de0db1c593e8d6d38859358a20ebb
parent 848726d8
Loading
Loading
Loading
Loading
+50 −15
Original line number Diff line number Diff line
@@ -756,7 +756,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
                    ALOGV("initiating %s decoder shutdown",
                         audio ? "audio" : "video");

                    (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
                    getDecoder(audio)->initiateShutdown();

                    if (audio) {
                        mFlushingAudio = SHUTTING_DOWN_DECODER;
@@ -1292,7 +1292,24 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
                mTimeDiscontinuityPending =
                    mTimeDiscontinuityPending || timeChange;

                if (mFlushingAudio == NONE && mFlushingVideo == NONE) {
                bool seamlessFormatChange = false;
                sp<AMessage> newFormat = mSource->getFormat(audio);
                if (formatChange) {
                    seamlessFormatChange =
                        getDecoder(audio)->supportsSeamlessFormatChange(newFormat);
                    // treat seamless format change separately
                    formatChange = !seamlessFormatChange;
                }
                bool shutdownOrFlush = formatChange || timeChange;

                // We want to queue up scan-sources only once per discontinuity.
                // We control this by doing it only if neither audio nor video are
                // flushing or shutting down.  (After handling 1st discontinuity, one
                // of the flushing states will not be NONE.)
                // No need to scan sources if this discontinuity does not result
                // in a flush or shutdown, as the flushing state will stay NONE.
                if (mFlushingAudio == NONE && mFlushingVideo == NONE &&
                        shutdownOrFlush) {
                    // And we'll resume scanning sources once we're done
                    // flushing.
                    mDeferredActions.push_front(
@@ -1300,16 +1317,17 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
                                &NuPlayer::performScanSources));
                }

                if (formatChange || timeChange) {

                    sp<AMessage> newFormat = mSource->getFormat(audio);
                    sp<Decoder> &decoder = audio ? mAudioDecoder : mVideoDecoder;
                    if (formatChange && !decoder->supportsSeamlessFormatChange(newFormat)) {
                if (formatChange /* not seamless */) {
                    // must change decoder
                    flushDecoder(audio, /* needShutdown = */ true);
                    } else {
                        flushDecoder(audio, /* needShutdown = */ false);
                } else if (timeChange) {
                    // need to flush
                    flushDecoder(audio, /* needShutdown = */ false, newFormat);
                    err = OK;
                } else if (seamlessFormatChange) {
                    // reuse existing decoder and don't flush
                    updateDecoderFormatWithoutFlush(audio, newFormat);
                    err = OK;
                    }
                } else {
                    // This stream is unaffected by the discontinuity
                    return -EWOULDBLOCK;
@@ -1488,20 +1506,23 @@ void NuPlayer::notifyListener(int msg, int ext1, int ext2, const Parcel *in) {
    driver->notifyListener(msg, ext1, ext2, in);
}

void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
void NuPlayer::flushDecoder(
        bool audio, bool needShutdown, const sp<AMessage> &newFormat) {
    ALOGV("[%s] flushDecoder needShutdown=%d",
          audio ? "audio" : "video", needShutdown);

    if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
    const sp<Decoder> &decoder = getDecoder(audio);
    if (decoder == NULL) {
        ALOGI("flushDecoder %s without decoder present",
             audio ? "audio" : "video");
        return;
    }

    // Make sure we don't continue to scan sources until we finish flushing.
    ++mScanSourcesGeneration;
    mScanSourcesPending = false;

    (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
    decoder->signalFlush(newFormat);
    mRenderer->flush(audio);

    FlushStatus newStatus =
@@ -1518,6 +1539,20 @@ void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
    }
}

void NuPlayer::updateDecoderFormatWithoutFlush(
        bool audio, const sp<AMessage> &format) {
    ALOGV("[%s] updateDecoderFormatWithoutFlush", audio ? "audio" : "video");

    const sp<Decoder> &decoder = getDecoder(audio);
    if (decoder == NULL) {
        ALOGI("updateDecoderFormatWithoutFlush %s without decoder present",
             audio ? "audio" : "video");
        return;
    }

    decoder->signalUpdateFormat(format);
}

void NuPlayer::queueDecoderShutdown(
        bool audio, bool video, const sp<AMessage> &reply) {
    ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video);
+8 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
namespace android {

struct ABuffer;
struct AMessage;
struct MetaData;
struct NuPlayerDriver;

@@ -169,6 +170,10 @@ private:

    bool mStarted;

    inline const sp<Decoder> &getDecoder(bool audio) {
        return audio ? mAudioDecoder : mVideoDecoder;
    }

    void openAudioSink(const sp<AMessage> &format, bool offloadOnly);
    void closeAudioSink();

@@ -185,7 +190,9 @@ private:

    void finishFlushIfPossible();

    void flushDecoder(bool audio, bool needShutdown);
    void flushDecoder(
            bool audio, bool needShutdown, const sp<AMessage> &newFormat = NULL);
    void updateDecoderFormatWithoutFlush(bool audio, const sp<AMessage> &format);

    static bool IsFlushingState(FlushStatus state, bool *needShutdown = NULL);

+53 −4
Original line number Diff line number Diff line
@@ -71,6 +71,19 @@ status_t PostAndAwaitResponse(
    return err;
}

void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
    mCSDsForCurrentFormat.clear();
    for (int32_t i = 0; ; ++i) {
        AString tag = "csd-";
        tag.append(i);
        sp<ABuffer> buffer;
        if (!format->findBuffer(tag.c_str(), &buffer)) {
            break;
        }
        mCSDsForCurrentFormat.push(buffer);
    }
}

void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
    CHECK(mCodec == NULL);

@@ -123,6 +136,8 @@ void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
        handleError(err);
        return;
    }
    rememberCodecSpecificData(format);

    // the following should work in configured state
    CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat));
    CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat));
@@ -189,6 +204,12 @@ void NuPlayer::Decoder::configure(const sp<AMessage> &format) {
    msg->post();
}

void NuPlayer::Decoder::signalUpdateFormat(const sp<AMessage> &format) {
    sp<AMessage> msg = new AMessage(kWhatUpdateFormat, id());
    msg->setMessage("format", format);
    msg->post();
}

status_t NuPlayer::Decoder::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
    sp<AMessage> msg = new AMessage(kWhatGetInputBuffers, id());
    msg->setPointer("buffers", buffers);
@@ -229,6 +250,15 @@ bool NuPlayer::Decoder::handleAnInputBuffer() {
    reply->setSize("buffer-ix", bufferIx);
    reply->setInt32("generation", mBufferGeneration);

    if (!mCSDsToSubmit.isEmpty()) {
        sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
        ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
        reply->setBuffer("buffer", buffer);
        mCSDsToSubmit.removeAt(0);
        reply->post();
        return true;
    }

    sp<AMessage> notify = mNotify->dup();
    notify->setInt32("what", kWhatFillThisBuffer);
    notify->setBuffer("buffer", mInputBuffers[bufferIx]);
@@ -312,10 +342,12 @@ void android::NuPlayer::Decoder::onInputBufferFilled(const sp<AMessage> &msg) {
        uint32_t flags = 0;
        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));

        int32_t eos;
        // we do not expect CODECCONFIG or SYNCFRAME for decoder
        int32_t eos, csd;
        // we do not expect SYNCFRAME for decoder
        if (buffer->meta()->findInt32("eos", &eos) && eos) {
            flags |= MediaCodec::BUFFER_FLAG_EOS;
        } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
            flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
        }

        // copy into codec buffer
@@ -448,6 +480,7 @@ void NuPlayer::Decoder::onFlush() {
    status_t err = OK;
    if (mCodec != NULL) {
        err = mCodec->flush();
        mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
        ++mBufferGeneration;
    }

@@ -515,6 +548,14 @@ void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
            break;
        }

        case kWhatUpdateFormat:
        {
            sp<AMessage> format;
            CHECK(msg->findMessage("format", &format));
            rememberCodecSpecificData(format);
            break;
        }

        case kWhatGetInputBuffers:
        {
            uint32_t replyID;
@@ -566,6 +607,10 @@ void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {

        case kWhatFlush:
        {
            sp<AMessage> format;
            if (msg->findMessage("new-format", &format)) {
                rememberCodecSpecificData(format);
            }
            onFlush();
            break;
        }
@@ -588,8 +633,12 @@ void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
    }
}

void NuPlayer::Decoder::signalFlush() {
    (new AMessage(kWhatFlush, id()))->post();
void NuPlayer::Decoder::signalFlush(const sp<AMessage> &format) {
    sp<AMessage> msg = new AMessage(kWhatFlush, id());
    if (format != NULL) {
        msg->setMessage("new-format", format);
    }
    msg->post();
}

void NuPlayer::Decoder::signalResume() {
+6 −1
Original line number Diff line number Diff line
@@ -36,7 +36,8 @@ struct NuPlayer::Decoder : public AHandler {
    virtual void init();

    status_t getInputBuffers(Vector<sp<ABuffer> > *dstBuffers) const;
    virtual void signalFlush();
    virtual void signalFlush(const sp<AMessage> &format = NULL);
    virtual void signalUpdateFormat(const sp<AMessage> &format);
    virtual void signalResume();
    virtual void initiateShutdown();

@@ -67,6 +68,7 @@ private:
        kWhatRenderBuffer       = 'rndr',
        kWhatFlush              = 'flus',
        kWhatShutdown           = 'shuD',
        kWhatUpdateFormat       = 'uFmt',
    };

    sp<AMessage> mNotify;
@@ -80,6 +82,8 @@ private:

    Vector<sp<ABuffer> > mInputBuffers;
    Vector<sp<ABuffer> > mOutputBuffers;
    Vector<sp<ABuffer> > mCSDsForCurrentFormat;
    Vector<sp<ABuffer> > mCSDsToSubmit;
    Vector<bool> mInputBufferIsDequeued;
    Vector<MediaBuffer *> mMediaBuffers;

@@ -103,6 +107,7 @@ private:
    AString mComponentName;

    bool supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const;
    void rememberCodecSpecificData(const sp<AMessage> &format);

    DISALLOW_EVIL_CONSTRUCTORS(Decoder);
};