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

Commit 66a051af authored by Andreas Huber's avatar Andreas Huber
Browse files

Finer granularity discontinuity support.

No clients can signal a format change on either audio or video track (or both)
and a time discontinuity (timestamps changed) independantly.

Change-Id: I3e6cf4e7c260e85759879d61a9b517f68431c22f
related-to-bug: 5553055
parent e35581ad
Loading
Loading
Loading
Loading
+55 −20
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ NuPlayer::NuPlayer()
      mVideoEOS(false),
      mScanSourcesPending(false),
      mScanSourcesGeneration(0),
      mTimeDiscontinuityPending(false),
      mFlushingAudio(NONE),
      mFlushingVideo(NONE),
      mResetInProgress(false),
@@ -477,6 +478,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
                break;
            }

            mTimeDiscontinuityPending = true;

            if (mAudioDecoder != NULL) {
                flushDecoder(true /* audio */, true /* needShutdown */);
            }
@@ -540,7 +543,10 @@ void NuPlayer::finishFlushIfPossible() {

    LOGV("both audio and video are flushed now.");

    if (mTimeDiscontinuityPending) {
        mRenderer->signalTimeDiscontinuity();
        mTimeDiscontinuityPending = false;
    }

    if (mAudioDecoder != NULL) {
        mAudioDecoder->signalResume();
@@ -663,10 +669,15 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
                CHECK(accessUnit->meta()->findInt32("discontinuity", &type));

                bool formatChange =
                    type == ATSParser::DISCONTINUITY_FORMATCHANGE;
                    (audio &&
                     (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
                    || (!audio &&
                            (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));

                bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;

                LOGV("%s discontinuity (formatChange=%d)",
                     audio ? "audio" : "video", formatChange);
                LOGI("%s discontinuity (formatChange=%d, time=%d)",
                     audio ? "audio" : "video", formatChange, timeChange);

                if (audio) {
                    mSkipRenderingAudioUntilMediaTimeUs = -1;
@@ -674,6 +685,7 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
                    mSkipRenderingVideoUntilMediaTimeUs = -1;
                }

                if (timeChange) {
                    sp<AMessage> extra;
                    if (accessUnit->meta()->findMessage("extra", &extra)
                            && extra != NULL) {
@@ -692,8 +704,26 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
                            }
                        }
                    }
                }

                mTimeDiscontinuityPending =
                    mTimeDiscontinuityPending || timeChange;

                if (formatChange || timeChange) {
                    flushDecoder(audio, formatChange);
                } else {
                    // This stream is unaffected by the discontinuity

                    if (audio) {
                        mFlushingAudio = FLUSHED;
                    } else {
                        mFlushingVideo = FLUSHED;
                    }

                    finishFlushIfPossible();

                    return -EWOULDBLOCK;
                }
            }

            reply->setInt32("err", err);
@@ -794,6 +824,11 @@ void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
}

void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
    if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
        LOGI("flushDecoder %s without decoder present",
             audio ? "audio" : "video");
    }

    // Make sure we don't continue to scan sources until we finish flushing.
    ++mScanSourcesGeneration;
    mScanSourcesPending = false;
+4 −0
Original line number Diff line number Diff line
@@ -112,6 +112,10 @@ private:
        SHUT_DOWN,
    };

    // Once the current flush is complete this indicates whether the
    // notion of time has changed.
    bool mTimeDiscontinuityPending;

    FlushStatus mFlushingAudio;
    FlushStatus mFlushingVideo;
    bool mResetInProgress;
+54 −31
Original line number Diff line number Diff line
@@ -123,6 +123,9 @@ private:

    void extractAACFrames(const sp<ABuffer> &buffer);

    bool isAudio() const;
    bool isVideo() const;

    DISALLOW_EVIL_CONSTRUCTORS(Stream);
};

@@ -401,7 +404,7 @@ ATSParser::Stream::Stream(
        case STREAMTYPE_H264:
            mQueue = new ElementaryStreamQueue(ElementaryStreamQueue::H264);
            break;
        case STREAMTYPE_MPEG2_AUDIO_ATDS:
        case STREAMTYPE_MPEG2_AUDIO_ADTS:
            mQueue = new ElementaryStreamQueue(ElementaryStreamQueue::AAC);
            break;
        case STREAMTYPE_MPEG1_AUDIO:
@@ -486,6 +489,31 @@ status_t ATSParser::Stream::parse(
    return OK;
}

bool ATSParser::Stream::isVideo() const {
    switch (mStreamType) {
        case STREAMTYPE_H264:
        case STREAMTYPE_MPEG1_VIDEO:
        case STREAMTYPE_MPEG2_VIDEO:
        case STREAMTYPE_MPEG4_VIDEO:
            return true;

        default:
            return false;
    }
}

bool ATSParser::Stream::isAudio() const {
    switch (mStreamType) {
        case STREAMTYPE_MPEG1_AUDIO:
        case STREAMTYPE_MPEG2_AUDIO:
        case STREAMTYPE_MPEG2_AUDIO_ADTS:
            return true;

        default:
            return false;
    }
}

void ATSParser::Stream::signalDiscontinuity(
        DiscontinuityType type, const sp<AMessage> &extra) {
    if (mQueue == NULL) {
@@ -495,14 +523,20 @@ void ATSParser::Stream::signalDiscontinuity(
    mPayloadStarted = false;
    mBuffer->setRange(0, 0);

    switch (type) {
        case DISCONTINUITY_SEEK:
        case DISCONTINUITY_FORMATCHANGE:
        {
            bool isASeek = (type == DISCONTINUITY_SEEK);
    bool clearFormat = false;
    if (isAudio()) {
        if (type & DISCONTINUITY_AUDIO_FORMAT) {
            clearFormat = true;
        }
    } else {
        if (type & DISCONTINUITY_VIDEO_FORMAT) {
            clearFormat = true;
        }
    }

            mQueue->clear(!isASeek);
    mQueue->clear(clearFormat);

    if (type & DISCONTINUITY_TIME) {
        uint64_t resumeAtPTS;
        if (extra != NULL
                && extra->findInt64(
@@ -513,17 +547,11 @@ void ATSParser::Stream::signalDiscontinuity(

            extra->setInt64("resume-at-mediatimeUs", resumeAtMediaTimeUs);
        }
    }

    if (mSource != NULL) {
        mSource->queueDiscontinuity(type, extra);
    }
            break;
        }

        default:
            TRESPASS();
            break;
    }
}

void ATSParser::Stream::signalEOS(status_t finalResult) {
@@ -764,10 +792,7 @@ sp<MediaSource> ATSParser::Stream::getSource(SourceType type) {
    switch (type) {
        case VIDEO:
        {
            if (mStreamType == STREAMTYPE_H264
                    || mStreamType == STREAMTYPE_MPEG1_VIDEO
                    || mStreamType == STREAMTYPE_MPEG2_VIDEO
                    || mStreamType == STREAMTYPE_MPEG4_VIDEO) {
            if (isVideo()) {
                return mSource;
            }
            break;
@@ -775,9 +800,7 @@ sp<MediaSource> ATSParser::Stream::getSource(SourceType type) {

        case AUDIO:
        {
            if (mStreamType == STREAMTYPE_MPEG1_AUDIO
                    || mStreamType == STREAMTYPE_MPEG2_AUDIO
                    || mStreamType == STREAMTYPE_MPEG2_AUDIO_ATDS) {
            if (isAudio()) {
                return mSource;
            }
            break;
+13 −4
Original line number Diff line number Diff line
@@ -33,9 +33,18 @@ struct MediaSource;

struct ATSParser : public RefBase {
    enum DiscontinuityType {
        DISCONTINUITY_NONE,
        DISCONTINUITY_SEEK,
        DISCONTINUITY_FORMATCHANGE
        DISCONTINUITY_NONE              = 0,
        DISCONTINUITY_TIME              = 1,
        DISCONTINUITY_AUDIO_FORMAT      = 2,
        DISCONTINUITY_VIDEO_FORMAT      = 4,

        DISCONTINUITY_SEEK              = DISCONTINUITY_TIME,

        // For legacy reasons this also implies a time discontinuity.
        DISCONTINUITY_FORMATCHANGE      =
            DISCONTINUITY_AUDIO_FORMAT
                | DISCONTINUITY_VIDEO_FORMAT
                | DISCONTINUITY_TIME,
    };

    enum Flags {
@@ -71,7 +80,7 @@ struct ATSParser : public RefBase {
        STREAMTYPE_MPEG2_VIDEO          = 0x02,
        STREAMTYPE_MPEG1_AUDIO          = 0x03,
        STREAMTYPE_MPEG2_AUDIO          = 0x04,
        STREAMTYPE_MPEG2_AUDIO_ATDS     = 0x0f,
        STREAMTYPE_MPEG2_AUDIO_ADTS     = 0x0f,
        STREAMTYPE_MPEG4_VIDEO          = 0x10,
        STREAMTYPE_H264                 = 0x1b,
    };
+21 −4
Original line number Diff line number Diff line
@@ -29,8 +29,17 @@
namespace android {

AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
    : mFormat(meta),
    : mIsAudio(false),
      mFormat(meta),
      mEOSResult(OK) {
    const char *mime;
    CHECK(meta->findCString(kKeyMIMEType, &mime));

    if (!strncasecmp("audio/", mime, 6)) {
        mIsAudio = true;
    } else {
        CHECK(!strncasecmp("video/", mime, 6));
    }
}

void AnotherPacketSource::setFormat(const sp<MetaData> &meta) {
@@ -67,8 +76,7 @@ status_t AnotherPacketSource::dequeueAccessUnit(sp<ABuffer> *buffer) {

        int32_t discontinuity;
        if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) {

            if (discontinuity == ATSParser::DISCONTINUITY_FORMATCHANGE) {
            if (wasFormatChange(discontinuity)) {
                mFormat.clear();
            }

@@ -96,7 +104,7 @@ status_t AnotherPacketSource::read(

        int32_t discontinuity;
        if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
            if (discontinuity == ATSParser::DISCONTINUITY_FORMATCHANGE) {
            if (wasFormatChange(discontinuity)) {
                mFormat.clear();
            }

@@ -117,6 +125,15 @@ status_t AnotherPacketSource::read(
    return mEOSResult;
}

bool AnotherPacketSource::wasFormatChange(
        int32_t discontinuityType) const {
    if (mIsAudio) {
        return (discontinuityType & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0;
    }

    return (discontinuityType & ATSParser::DISCONTINUITY_VIDEO_FORMAT) != 0;
}

void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
    int32_t damaged;
    if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
Loading