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

Commit 1734c7d0 authored by Lajos Molnar's avatar Lajos Molnar
Browse files

stagefright: detect output format changes without event

Bug: 27688967
Change-Id: I538560e61928903160333866886dbc763503546f
parent 287b36cf
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -506,7 +506,10 @@ private:
    void notifyOfRenderedFrames(
            bool dropIncomplete = false, FrameRenderTracker::Info *until = NULL);

    void onOutputFormatChanged();
    // Pass |expectedFormat| to print a warning if the format differs from it.
    // Using sp<> instead of const sp<>& because expectedFormat is likely the current mOutputFormat
    // which will get updated inside.
    void onOutputFormatChanged(sp<const AMessage> expectedFormat = NULL);
    void addKeyFormatChangesToRenderBufferNotification(sp<AMessage> &notify);
    void sendFormatChange();

+9 −0
Original line number Diff line number Diff line
@@ -127,6 +127,15 @@ struct AMessage : public RefBase {
    // their refcount incremented.
    sp<AMessage> dup() const;

    // Performs a shallow or deep comparison of |this| and |other| and returns
    // an AMessage with the differences.
    // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
    // their refcount incremented.
    // This is true for AMessages that have no corresponding AMessage equivalent in |other|.
    // (E.g. there is no such key or the type is different.) On the other hand, changes in
    // the AMessage (or AMessages if deep is |false|) are returned in new objects.
    sp<AMessage> changesFrom(const sp<const AMessage> &other, bool deep = false) const;

    AString debugString(int32_t indent = 0) const;

    enum Type {
+12 −2
Original line number Diff line number Diff line
@@ -5019,7 +5019,7 @@ void ACodec::onDataSpaceChanged(android_dataspace dataSpace, const ColorAspects
            transfer, asString((ColorTransfer)transfer));
}

void ACodec::onOutputFormatChanged() {
void ACodec::onOutputFormatChanged(sp<const AMessage> expectedFormat) {
    // store new output format, at the same time mark that this is no longer the first frame
    mOutputFormat = mBaseOutputFormat->dup();

@@ -5028,6 +5028,16 @@ void ACodec::onOutputFormatChanged() {
        return;
    }

    if (expectedFormat != NULL) {
        sp<const AMessage> changes = expectedFormat->changesFrom(mOutputFormat);
        sp<const AMessage> to = mOutputFormat->changesFrom(expectedFormat);
        if (changes->countEntries() != 0 || to->countEntries() != 0) {
            ALOGW("[%s] BAD CODEC: Output format changed unexpectedly from (diff) %s to (diff) %s",
                    mComponentName.c_str(),
                    changes->debugString(4).c_str(), to->debugString(4).c_str());
        }
    }

    if (!mIsVideo && !mIsEncoder) {
        AudioEncoding pcmEncoding = kAudioEncodingPcm16bit;
        (void)mConfigFormat->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
@@ -5805,7 +5815,7 @@ bool ACodec::BaseState::onOMXFillBufferDone(
            if (mCodec->mOutputFormat != mCodec->mLastOutputFormat && rangeLength > 0) {
                // pretend that output format has changed on the first frame (we used to do this)
                if (mCodec->mBaseOutputFormat == mCodec->mOutputFormat) {
                    mCodec->onOutputFormatChanged();
                    mCodec->onOutputFormatChanged(mCodec->mOutputFormat);
                }
                mCodec->addKeyFormatChangesToRenderBufferNotification(reply);
                mCodec->sendFormatChange();
+120 −0
Original line number Diff line number Diff line
@@ -749,6 +749,126 @@ void AMessage::writeToParcel(Parcel *parcel) const {
    }
}

sp<AMessage> AMessage::changesFrom(const sp<const AMessage> &other, bool deep) const {
    if (other == NULL) {
        return const_cast<AMessage*>(this);
    }

    sp<AMessage> diff = new AMessage;
    if (mWhat != other->mWhat) {
        diff->setWhat(mWhat);
    }
    if (mHandler != other->mHandler) {
        diff->setTarget(mHandler.promote());
    }

    for (size_t i = 0; i < mNumItems; ++i) {
        const Item &item = mItems[i];
        const Item *oitem = other->findItem(item.mName, item.mType);
        switch (item.mType) {
            case kTypeInt32:
                if (oitem == NULL || item.u.int32Value != oitem->u.int32Value) {
                    diff->setInt32(item.mName, item.u.int32Value);
                }
                break;

            case kTypeInt64:
                if (oitem == NULL || item.u.int64Value != oitem->u.int64Value) {
                    diff->setInt64(item.mName, item.u.int64Value);
                }
                break;

            case kTypeSize:
                if (oitem == NULL || item.u.sizeValue != oitem->u.sizeValue) {
                    diff->setSize(item.mName, item.u.sizeValue);
                }
                break;

            case kTypeFloat:
                if (oitem == NULL || item.u.floatValue != oitem->u.floatValue) {
                    diff->setFloat(item.mName, item.u.sizeValue);
                }
                break;

            case kTypeDouble:
                if (oitem == NULL || item.u.doubleValue != oitem->u.doubleValue) {
                    diff->setDouble(item.mName, item.u.sizeValue);
                }
                break;

            case kTypeString:
                if (oitem == NULL || *item.u.stringValue != *oitem->u.stringValue) {
                    diff->setString(item.mName, *item.u.stringValue);
                }
                break;

            case kTypeRect:
                if (oitem == NULL || memcmp(&item.u.rectValue, &oitem->u.rectValue, sizeof(Rect))) {
                    diff->setRect(
                            item.mName, item.u.rectValue.mLeft, item.u.rectValue.mTop,
                            item.u.rectValue.mRight, item.u.rectValue.mBottom);
                }
                break;

            case kTypePointer:
                if (oitem == NULL || item.u.ptrValue != oitem->u.ptrValue) {
                    diff->setPointer(item.mName, item.u.ptrValue);
                }
                break;

            case kTypeBuffer:
            {
                sp<ABuffer> myBuf = static_cast<ABuffer *>(item.u.refValue);
                if (myBuf == NULL) {
                    if (oitem == NULL || oitem->u.refValue != NULL) {
                        diff->setBuffer(item.mName, NULL);
                    }
                    break;
                }
                sp<ABuffer> oBuf = oitem == NULL ? NULL : static_cast<ABuffer *>(oitem->u.refValue);
                if (oBuf == NULL
                        || myBuf->size() != oBuf->size()
                        || (!myBuf->data() ^ !oBuf->data()) // data nullness differs
                        || (myBuf->data() && memcmp(myBuf->data(), oBuf->data(), myBuf->size()))) {
                    diff->setBuffer(item.mName, myBuf);
                }
                break;
            }

            case kTypeMessage:
            {
                sp<AMessage> myMsg = static_cast<AMessage *>(item.u.refValue);
                if (myMsg == NULL) {
                    if (oitem == NULL || oitem->u.refValue != NULL) {
                        diff->setMessage(item.mName, NULL);
                    }
                    break;
                }
                sp<AMessage> oMsg =
                    oitem == NULL ? NULL : static_cast<AMessage *>(oitem->u.refValue);
                sp<AMessage> changes = myMsg->changesFrom(oMsg, deep);
                if (changes->countEntries()) {
                    diff->setMessage(item.mName, deep ? changes : myMsg);
                }
                break;
            }

            case kTypeObject:
                if (oitem == NULL || item.u.refValue != oitem->u.refValue) {
                    diff->setObject(item.mName, item.u.refValue);
                }
                break;

            default:
            {
                ALOGE("Unknown type %d", item.mType);
                TRESPASS();
            }
        }
    }
    return diff;
}

size_t AMessage::countEntries() const {
    return mNumItems;
}