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

Commit 0e7d8739 authored by Guillaume Chelfi's avatar Guillaume Chelfi Committed by Android (Google) Code Review
Browse files

Merge changes from topic "atv-tunnel-mode-s" into sc-dev

* changes:
  Implement peek mode state tracking in MediaCodec
  Forward first tunnel frame OMX event to framework
  Forward tunnel peek flag to OMX implementation
parents bb572630 4249d164
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -74,6 +74,12 @@ enum {
    kMaxIndicesToCheck = 32, // used when enumerating supported formats and profiles
};

namespace {

constexpr char TUNNEL_PEEK_KEY[] = "android._trigger-tunnel-peek";

}

// OMX errors are directly mapped into status_t range if
// there is no corresponding MediaError status code.
// Use the statusFromOMXError(int32_t omxError) function.
@@ -1465,6 +1471,10 @@ void ACodec::notifyOfRenderedFrames(bool dropIncomplete, FrameRenderTracker::Inf
    mCallback->onOutputFramesRendered(done);
}

void ACodec::onFirstTunnelFrameReady() {
    mCallback->onFirstTunnelFrameReady();
}

ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
    ANativeWindowBuffer *buf;
    CHECK(mNativeWindow.get() != NULL);
@@ -2460,6 +2470,30 @@ status_t ACodec::getLatency(uint32_t *latency) {
    return err;
}

status_t ACodec::setTunnelPeek(int32_t tunnelPeek) {
    if (mIsEncoder) {
        ALOGE("encoder does not support %s", TUNNEL_PEEK_KEY);
        return BAD_VALUE;
    }
    if (!mTunneled) {
        ALOGE("%s is only supported in tunnel mode", TUNNEL_PEEK_KEY);
        return BAD_VALUE;
    }

    OMX_CONFIG_BOOLEANTYPE config;
    InitOMXParams(&config);
    config.bEnabled = (OMX_BOOL)(tunnelPeek != 0);
    status_t err = mOMXNode->setConfig(
            (OMX_INDEXTYPE)OMX_IndexConfigAndroidTunnelPeek,
            &config, sizeof(config));
    if (err != OK) {
        ALOGE("decoder cannot set %s to %d (err %d)",
              TUNNEL_PEEK_KEY, tunnelPeek, err);
    }

    return err;
}

status_t ACodec::setAudioPresentation(int32_t presentationId, int32_t programId) {
    OMX_AUDIO_CONFIG_ANDROID_AUDIOPRESENTATION config;
    InitOMXParams(&config);
@@ -7890,6 +7924,15 @@ status_t ACodec::setParameters(const sp<AMessage> &params) {
                &presentation, sizeof(presentation));
        }
    }

    int32_t tunnelPeek = 0;
    if (params->findInt32(TUNNEL_PEEK_KEY, &tunnelPeek)) {
        status_t err = setTunnelPeek(tunnelPeek);
        if (err != OK) {
            return err;
        }
    }

    return setVendorParameters(params);
}

@@ -8355,6 +8398,12 @@ bool ACodec::ExecutingState::onOMXEvent(
            return true;
        }

        case OMX_EventOnFirstTunnelFrameReady:
        {
            mCodec->onFirstTunnelFrameReady();
            return true;
        }

        default:
            return BaseState::onOMXEvent(event, data1, data2);
    }
+116 −3
Original line number Diff line number Diff line
@@ -424,6 +424,7 @@ enum {
    kWhatSignaledInputEOS    = 'seos',
    kWhatOutputFramesRendered = 'outR',
    kWhatOutputBuffersChanged = 'outC',
    kWhatFirstTunnelFrameReady = 'ftfR',
};

class BufferCallback : public CodecBase::BufferCallback {
@@ -486,6 +487,7 @@ public:
    virtual void onSignaledInputEOS(status_t err) override;
    virtual void onOutputFramesRendered(const std::list<FrameRenderTracker::Info> &done) override;
    virtual void onOutputBuffersChanged() override;
    virtual void onFirstTunnelFrameReady() override;
private:
    const sp<AMessage> mNotify;
};
@@ -606,6 +608,12 @@ void CodecCallback::onOutputBuffersChanged() {
    notify->post();
}

void CodecCallback::onFirstTunnelFrameReady() {
    sp<AMessage> notify(mNotify->dup());
    notify->setInt32("what", kWhatFirstTunnelFrameReady);
    notify->post();
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
@@ -704,6 +712,7 @@ MediaCodec::MediaCodec(
      mTunneledInputWidth(0),
      mTunneledInputHeight(0),
      mTunneled(false),
      mTunnelPeekState(TunnelPeekState::kEnabledNoBuffer),
      mHaveInputSurface(false),
      mHavePendingInputBuffers(false),
      mCpuBoostRequested(false),
@@ -909,6 +918,47 @@ void MediaCodec::updateLowLatency(const sp<AMessage> &msg) {
    }
}

constexpr const char *MediaCodec::asString(TunnelPeekState state, const char *default_string){
    switch(state) {
        case TunnelPeekState::kEnabledNoBuffer:
            return "EnabledNoBuffer";
        case TunnelPeekState::kDisabledNoBuffer:
            return "DisabledNoBuffer";
        case TunnelPeekState::kBufferDecoded:
            return "BufferDecoded";
        case TunnelPeekState::kBufferRendered:
            return "BufferRendered";
        default:
            return default_string;
    }
}

void MediaCodec::updateTunnelPeek(const sp<AMessage> &msg) {
    int32_t tunnelPeek = 0;
    if (!msg->findInt32("tunnel-peek", &tunnelPeek)){
        return;
    }
    if(tunnelPeek == 0){
        if (mTunnelPeekState == TunnelPeekState::kEnabledNoBuffer) {
            mTunnelPeekState = TunnelPeekState::kDisabledNoBuffer;
            ALOGV("TunnelPeekState: %s -> %s",
                  asString(TunnelPeekState::kEnabledNoBuffer),
                  asString(TunnelPeekState::kDisabledNoBuffer));
            return;
        }
    } else {
        if (mTunnelPeekState == TunnelPeekState::kDisabledNoBuffer) {
            mTunnelPeekState = TunnelPeekState::kEnabledNoBuffer;
            ALOGV("TunnelPeekState: %s -> %s",
                  asString(TunnelPeekState::kDisabledNoBuffer),
                  asString(TunnelPeekState::kEnabledNoBuffer));
            return;
        }
    }

    ALOGV("Ignoring tunnel-peek=%d for %s", tunnelPeek, asString(mTunnelPeekState));
}

bool MediaCodec::Histogram::setup(int nbuckets, int64_t width, int64_t floor)
{
    if (nbuckets <= 0 || width <= 0) {
@@ -1334,6 +1384,12 @@ status_t MediaCodec::setOnFrameRenderedNotification(const sp<AMessage> &notify)
    return msg->post();
}

status_t MediaCodec::setOnFirstTunnelFrameReadyNotification(const sp<AMessage> &notify) {
    sp<AMessage> msg = new AMessage(kWhatSetNotification, this);
    msg->setMessage("first-tunnel-frame-ready", notify);
    return msg->post();
}

static void mapFormat(AString componentName, const sp<AMessage> &format, const char *kind,
                      bool reverse);

@@ -2993,9 +3049,17 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {

                case kWhatOutputFramesRendered:
                {
                    // ignore these in all states except running, and check that we have a
                    // notification set
                    if (mState == STARTED && mOnFrameRenderedNotification != NULL) {
                    // ignore these in all states except running
                    if (mState != STARTED) {
                        break;
                    }
                    TunnelPeekState previousState = mTunnelPeekState;
                    mTunnelPeekState = TunnelPeekState::kBufferRendered;
                    ALOGV("TunnelPeekState: %s -> %s",
                          asString(previousState),
                          asString(TunnelPeekState::kBufferRendered));
                    // check that we have a notification set
                    if (mOnFrameRenderedNotification != NULL) {
                        sp<AMessage> notify = mOnFrameRenderedNotification->dup();
                        notify->setMessage("data", msg);
                        notify->post();
@@ -3003,6 +3067,41 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                    break;
                }

                case kWhatFirstTunnelFrameReady:
                {
                    if (mState != STARTED) {
                        break;
                    }
                    switch(mTunnelPeekState) {
                        case TunnelPeekState::kDisabledNoBuffer:
                            mTunnelPeekState = TunnelPeekState::kBufferDecoded;
                            ALOGV("TunnelPeekState: %s -> %s",
                                  asString(TunnelPeekState::kDisabledNoBuffer),
                                  asString(TunnelPeekState::kBufferDecoded));
                            break;
                        case TunnelPeekState::kEnabledNoBuffer:
                            mTunnelPeekState = TunnelPeekState::kBufferDecoded;
                            ALOGV("TunnelPeekState: %s -> %s",
                                  asString(TunnelPeekState::kEnabledNoBuffer),
                                  asString(TunnelPeekState::kBufferDecoded));
                            {
                                sp<AMessage> parameters = new AMessage();
                                parameters->setInt32("android._trigger-tunnel-peek", 1);
                                mCodec->signalSetParameters(parameters);
                            }
                            break;
                        default:
                            break;
                    }

                    if (mOnFirstTunnelFrameReadyNotification != nullptr) {
                        sp<AMessage> notify = mOnFirstTunnelFrameReadyNotification->dup();
                        notify->setMessage("data", msg);
                        notify->post();
                    }
                    break;
                }

                case kWhatFillThisBuffer:
                {
                    /* size_t index = */updateBuffers(kPortIndexInput, msg);
@@ -3221,6 +3320,9 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
            if (msg->findMessage("on-frame-rendered", &notify)) {
                mOnFrameRenderedNotification = notify;
            }
            if (msg->findMessage("first-tunnel-frame-ready", &notify)) {
                mOnFirstTunnelFrameReadyNotification = notify;
            }
            break;
        }

@@ -3462,6 +3564,11 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
            }
            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));
            TunnelPeekState previousState = mTunnelPeekState;
            mTunnelPeekState = TunnelPeekState::kEnabledNoBuffer;
            ALOGV("TunnelPeekState: %s -> %s",
                  asString(previousState),
                  asString(TunnelPeekState::kEnabledNoBuffer));

            mReplyID = replyID;
            setState(STARTING);
@@ -3896,6 +4003,11 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {

            mCodec->signalFlush();
            returnBuffersToCodec();
            TunnelPeekState previousState = mTunnelPeekState;
            mTunnelPeekState = TunnelPeekState::kEnabledNoBuffer;
            ALOGV("TunnelPeekState: %s -> %s",
                  asString(previousState),
                  asString(TunnelPeekState::kEnabledNoBuffer));
            break;
        }

@@ -4806,6 +4918,7 @@ status_t MediaCodec::setParameters(const sp<AMessage> &params) {
status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
    updateLowLatency(params);
    mapFormat(mComponentName, params, nullptr, false);
    updateTunnelPeek(params);
    mCodec->signalSetParameters(params);

    return OK;
+3 −0
Original line number Diff line number Diff line
@@ -518,6 +518,7 @@ private:
    status_t setLowLatency(int32_t lowLatency);
    status_t setLatency(uint32_t latency);
    status_t getLatency(uint32_t *latency);
    status_t setTunnelPeek(int32_t tunnelPeek);
    status_t setAudioPresentation(int32_t presentationId, int32_t programId);
    status_t setOperatingRate(float rateFloat, bool isVideo);
    status_t getIntraRefreshPeriod(uint32_t *intraRefreshPeriod);
@@ -578,6 +579,8 @@ private:
    void notifyOfRenderedFrames(
            bool dropIncomplete = false, FrameRenderTracker::Info *until = NULL);

    void onFirstTunnelFrameReady();

    // 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.
+4 −0
Original line number Diff line number Diff line
@@ -173,6 +173,10 @@ struct CodecBase : public AHandler, /* static */ ColorUtils {
         * Notify MediaCodec that output buffers are changed.
         */
        virtual void onOutputBuffersChanged() = 0;
        /**
         * Notify MediaCodec that the first tunnel frame is ready.
         */
        virtual void onFirstTunnelFrameReady() = 0;
    };

    /**
+22 −0
Original line number Diff line number Diff line
@@ -128,6 +128,8 @@ struct MediaCodec : public AHandler {

    status_t setOnFrameRenderedNotification(const sp<AMessage> &notify);

    status_t setOnFirstTunnelFrameReadyNotification(const sp<AMessage> &notify);

    status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer);

    status_t setInputSurface(const sp<PersistentSurface> &surface);
@@ -361,6 +363,22 @@ private:
        bool mOwnedByClient;
    };

    // This type is used to track the tunnel mode video peek state machine:
    //
    // DisabledNoBuffer -> EnabledNoBuffer  when tunnel-peek = true
    // EnabledNoBuffer  -> DisabledNoBuffer when tunnel-peek = false
    // DisabledNoBuffer -> BufferDecoded    when kWhatFirstTunnelFrameReady
    // EnabledNoBuffer  -> BufferDecoded    when kWhatFirstTunnelFrameReady
    // BufferDecoded    -> BufferRendered   when kWhatFrameRendered
    // <all states>     -> EnabledNoBuffer  when flush
    // <all states>     -> EnabledNoBuffer  when stop then configure then start
    enum struct TunnelPeekState {
        kDisabledNoBuffer,
        kEnabledNoBuffer,
        kBufferDecoded,
        kBufferRendered,
    };

    struct ResourceManagerServiceProxy;

    State mState;
@@ -387,12 +405,15 @@ private:
    void flushMediametrics();
    void updateEphemeralMediametrics(mediametrics_handle_t item);
    void updateLowLatency(const sp<AMessage> &msg);
    constexpr const char *asString(TunnelPeekState state, const char *default_string="?");
    void updateTunnelPeek(const sp<AMessage> &msg);

    sp<AMessage> mOutputFormat;
    sp<AMessage> mInputFormat;
    sp<AMessage> mCallback;
    sp<AMessage> mOnFrameRenderedNotification;
    sp<AMessage> mAsyncReleaseCompleteNotification;
    sp<AMessage> mOnFirstTunnelFrameReadyNotification;

    sp<ResourceManagerServiceProxy> mResourceManagerProxy;

@@ -439,6 +460,7 @@ private:
    int32_t mTunneledInputWidth;
    int32_t mTunneledInputHeight;
    bool mTunneled;
    TunnelPeekState mTunnelPeekState;

    sp<IDescrambler> mDescrambler;

Loading