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

Commit a5351c7d authored by Sungtak Lee's avatar Sungtak Lee
Browse files

Codec2Client: add c2 aidl HAL inputsurface

Add codec2 aidl HAL inputsurface.

Bug: 201479783
Flag: EXEMPT refactor
Change-Id: I9ede98c45c0822e3defca8043d49119f0ae6964f
parent cdadd646
Loading
Loading
Loading
Loading
+89 −141
Original line number Diff line number Diff line
@@ -2281,30 +2281,22 @@ c2_status_t Codec2Client::createInputSurface(
        // Not supported for APEX.
        return C2_OMITTED;
    }
    if (mAidlBase) {
        // FIXME
    if (!mAidlBase) {
        // Only AIDL supports InputSurface.
        return C2_OMITTED;
    }

    c2_status_t status;
    Return<void> transStatus = mHidlBase1_0->createInputSurface(
            [&status, inputSurface](
                    c2_hidl::Status s,
                    const sp<c2_hidl::IInputSurface>& i) {
                status = static_cast<c2_status_t>(s);
                if (status != C2_OK) {
                    return;
    if (!IsCodec2AidlInputSurfaceSelected()) {
        return C2_OMITTED;
    }
                *inputSurface = std::make_shared<InputSurface>(i);
            });
    if (!transStatus.isOk()) {
        LOG(ERROR) << "createInputSurface -- transaction failed.";
        return C2_TRANSACTION_FAILED;
    } else if (status != C2_OK) {
        LOG(DEBUG) << "createInputSurface -- call failed: "
                   << status << ".";
    std::shared_ptr<c2_aidl::IInputSurface> interface;
    ndk::ScopedAStatus status = mAidlBase->createInputSurface(&interface);
    c2_status_t c2Status = GetC2Status(status, "createInputSurface");
    if (c2Status != C2_OK) {
        LOG(ERROR) << "createInputSurface() failed: " << c2Status;
        return c2Status;
    }
    return status;
    *inputSurface = std::make_shared<InputSurface>(interface);
    return C2_OK;
}

std::vector<C2Component::Traits> const& Codec2Client::listComponents() const {
@@ -2823,6 +2815,12 @@ std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurface(
    return nullptr;
}

std::shared_ptr<Codec2Client::InputSurface> Codec2Client::CreateInputSurfaceFromInterface(
        const ::ndk::SpAIBinder &interface) {
    return std::make_shared<Codec2Client::InputSurface>(
            c2_aidl::IInputSurface::fromBinder(interface));
}

bool Codec2Client::IsAidlSelected() {
    return c2_aidl::utils::IsSelected();
}
@@ -3674,92 +3672,6 @@ void Codec2Client::Component::holdIgbaBlocks(
    }
}

c2_status_t Codec2Client::Component::connectToInputSurface(
        const std::shared_ptr<InputSurface>& inputSurface,
        std::shared_ptr<InputSurfaceConnection>* connection) {
    if (mApexBase) {
        // FIXME
        return C2_OMITTED;
    }
    if (mAidlBase) {
        // FIXME
        return C2_OMITTED;
    }
    c2_status_t status;
    Return<void> transStatus = mHidlBase1_0->connectToInputSurface(
            inputSurface->mBase,
            [&status, connection](
                    c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
                status = static_cast<c2_status_t>(s);
                if (status != C2_OK) {
                    LOG(DEBUG) << "connectToInputSurface -- call failed: "
                               << status << ".";
                    return;
                }
                *connection = std::make_shared<InputSurfaceConnection>(c);
            });
    if (!transStatus.isOk()) {
        LOG(ERROR) << "connectToInputSurface -- transaction failed";
        return C2_TRANSACTION_FAILED;
    }
    return status;
}

c2_status_t Codec2Client::Component::connectToOmxInputSurface(
        const sp<HGraphicBufferProducer1>& producer,
        const sp<HGraphicBufferSource>& source,
        std::shared_ptr<InputSurfaceConnection>* connection) {
    if (mApexBase) {
        LOG(WARNING) << "Connecting to OMX input surface is not supported for AIDL C2 HAL";
        return C2_OMITTED;
    }
    if (mAidlBase) {
        LOG(WARNING) << "Connecting to OMX input surface is not supported for AIDL C2 HAL";
        return C2_OMITTED;
    }
    c2_status_t status;
    Return<void> transStatus = mHidlBase1_0->connectToOmxInputSurface(
            producer, source,
            [&status, connection](
                    c2_hidl::Status s, const sp<c2_hidl::IInputSurfaceConnection>& c) {
                status = static_cast<c2_status_t>(s);
                if (status != C2_OK) {
                    LOG(DEBUG) << "connectToOmxInputSurface -- call failed: "
                               << status << ".";
                    return;
                }
                *connection = std::make_shared<InputSurfaceConnection>(c);
            });
    if (!transStatus.isOk()) {
        LOG(ERROR) << "connectToOmxInputSurface -- transaction failed.";
        return C2_TRANSACTION_FAILED;
    }
    return status;
}

c2_status_t Codec2Client::Component::disconnectFromInputSurface() {
    if (mApexBase) {
        // FIXME
        return C2_OMITTED;
    }
    if (mAidlBase) {
        // FIXME
        return C2_OMITTED;
    }
    Return<c2_hidl::Status> transStatus = mHidlBase1_0->disconnectFromInputSurface();
    if (!transStatus.isOk()) {
        LOG(ERROR) << "disconnectToInputSurface -- transaction failed.";
        return C2_TRANSACTION_FAILED;
    }
    c2_status_t status =
            static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transStatus));
    if (status != C2_OK) {
        LOG(DEBUG) << "disconnectFromInputSurface -- call failed: "
                   << status << ".";
    }
    return status;
}

Codec2Client::Component::AidlDeathManager *Codec2Client::Component::GetAidlDeathManager() {
    // This object never gets destructed
    static AidlDeathManager *sManager = new AidlDeathManager();
@@ -3823,54 +3735,90 @@ c2_status_t Codec2Client::Component::setDeathListener(
}

// Codec2Client::InputSurface
Codec2Client::InputSurface::InputSurface(const sp<c2_hidl::IInputSurface>& base)
Codec2Client::InputSurface::InputSurface(const std::shared_ptr<c2_aidl::IInputSurface>& base)
      : Configurable{
            [base]() -> sp<c2_hidl::IConfigurable> {
                Return<sp<c2_hidl::IConfigurable>> transResult =
                        base->getConfigurable();
                return transResult.isOk() ?
                        static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
                        nullptr;
            [base]() -> std::shared_ptr<c2_aidl::IConfigurable> {
                std::shared_ptr<c2_aidl::IConfigurable> aidlConfigurable;
                ::ndk::ScopedAStatus transStatus =
                    base->getConfigurable(&aidlConfigurable);
                return transStatus.isOk() ? aidlConfigurable : nullptr;
            }()
        },
        mBase{base},
        mGraphicBufferProducer{new
            H2BGraphicBufferProducer2([base]() -> sp<HGraphicBufferProducer2> {
                Return<sp<HGraphicBufferProducer2>> transResult =
                        base->getGraphicBufferProducer();
                return transResult.isOk() ?
                        static_cast<sp<HGraphicBufferProducer2>>(transResult) :
                        nullptr;
            }())} {
        mBase{base}, mNativeWindow{nullptr} {
}

sp<IGraphicBufferProducer>
        Codec2Client::InputSurface::getGraphicBufferProducer() const {
    return mGraphicBufferProducer;
ANativeWindow *Codec2Client::InputSurface::getNativeWindow() {
    std::call_once(mWindowInitOnce, [this]() {
        ::aidl::android::view::Surface surface;
        ::ndk::ScopedAStatus transStatus = mBase->getSurface(&surface);
        c2_status_t c2Status = GetC2Status(transStatus, "InputSurface::getNativeWindow");
        if (c2Status != C2_OK) {
            LOG(ERROR) << "InputSurface::getNativeWindow -- cannot get window: " << c2Status;
            return;
        }
        mNativeWindow = surface.release();
    });
    return mNativeWindow;
}

sp<c2_hidl::IInputSurface> Codec2Client::InputSurface::getHalInterface() const {
    return mBase;
::ndk::SpAIBinder Codec2Client::InputSurface::getHalInterface() const {
    return mBase ? mBase->asBinder() : nullptr;
}

c2_status_t Codec2Client::InputSurface::connect(
        const std::shared_ptr<Codec2Client::Component> &comp,
        std::shared_ptr<Connection> *connection) {
    if (!comp) {
        LOG(ERROR) << "InputSurface:connect, component invalid";
        return C2_BAD_VALUE;
    }
    std::shared_ptr<Codec2Client::Component::AidlBase> aidlBase = comp->mAidlBase;
    if (!aidlBase) {
        LOG(ERROR) << "InputSurface:connect, component invalid";
        return C2_BAD_VALUE;
    }
    std::shared_ptr<c2_aidl::IInputSink> sink;
    ::ndk::ScopedAStatus transResult = aidlBase->asInputSink(&sink);
    if (GetC2Status(transResult, "InputSurface:Component:asInputSink") != C2_OK) {
        LOG(ERROR) << "InputSurface:connect sink conversion failed";
        return C2_CORRUPTED;
    }
    if (!mBase) {
        LOG(ERROR) << "InputSurface:connect failed, no valid base";
        return C2_CORRUPTED;
    }
    std::shared_ptr<ConnectionBase> base;
    transResult = mBase->connect(sink, &base);
    c2_status_t c2Status = GetC2Status(transResult, "InputSurface:connect");
    if (c2Status != C2_OK) {
        LOG(ERROR) << "IInputSurface:connect failed: " << c2Status;
        return c2Status;
    }
    *connection = std::make_shared<Connection>(base);
    return C2_OK;
}

// Codec2Client::InputSurfaceConnection
Codec2Client::InputSurfaceConnection::InputSurfaceConnection(
        const sp<c2_hidl::IInputSurfaceConnection>& base)
      : Configurable{
            [base]() -> sp<c2_hidl::IConfigurable> {
                Return<sp<c2_hidl::IConfigurable>> transResult =
                        base->getConfigurable();
                return transResult.isOk() ?
                        static_cast<sp<c2_hidl::IConfigurable>>(transResult) :
                        nullptr;
            }()
        },
        mBase{base} {
        const std::shared_ptr<c2_aidl::IInputSurfaceConnection>& base) : mBase{base} {
}

c2_status_t Codec2Client::InputSurfaceConnection::disconnect() {
    Return<c2_hidl::Status> transResult = mBase->disconnect();
    return static_cast<c2_status_t>(static_cast<c2_hidl::Status>(transResult));
    if (!mBase) {
        LOG(ERROR) << "InputSurfaceConnection:disconnect failed, no valid base";
        return C2_CORRUPTED;
    }
    ::ndk::ScopedAStatus transResult = mBase->disconnect();
    return GetC2Status(transResult, "InputSurfaceConnection::disconnect");
}

c2_status_t Codec2Client::InputSurfaceConnection::signalEos() {
    if (!mBase) {
        LOG(ERROR) << "InputSurfaceConnection:signalEos failed, no valid base";
        return C2_CORRUPTED;
    }
    ::ndk::ScopedAStatus transResult = mBase->signalEndOfStream();
    return GetC2Status(transResult, "InputSurfaceConnection::signalEndOfStream");
}

}  // namespace android
+57 −29
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <C2Param.h>
#include <C2.h>

#include <android/native_window_aidl.h>
#include <gui/FrameTimestamps.h>
#include <gui/IGraphicBufferProducer.h>
#include <hidl/HidlSupport.h>
@@ -69,9 +70,6 @@ struct IConfigurable;
struct IComponent;
struct IComponentInterface;
struct IComponentStore;
struct IInputSink;
struct IInputSurface;
struct IInputSurfaceConnection;
}  // namespace android::hardware::media::c2::V1_0

namespace android::hardware::media::c2::V1_1 {
@@ -89,6 +87,9 @@ class IComponent;
class IComponentInterface;
class IComponentStore;
class IConfigurable;
class IInputSink;
class IInputSurface;
class IInputSurfaceConnection;
}  // namespace aidl::android::hardware::media::c2

namespace android::hardware::media::bufferpool::V2_0 {
@@ -190,6 +191,7 @@ struct Codec2Client : public Codec2ConfigurableClient {
    typedef HidlBase1_0 HidlBase;

    typedef ::aidl::android::hardware::media::c2::IComponentStore AidlBase;
    typedef ::aidl::android::hardware::media::c2::IInputSurface IInputSurface;

    struct Listener;

@@ -276,6 +278,10 @@ struct Codec2Client : public Codec2ConfigurableClient {
    static std::shared_ptr<InputSurface> CreateInputSurface(
            char const* serviceName = nullptr);

    // Create an input surface from an existing interface.
    static std::shared_ptr<InputSurface> CreateInputSurfaceFromInterface(
            const ::ndk::SpAIBinder &interface);

    // Whether AIDL is selected.
    static bool IsAidlSelected();

@@ -523,18 +529,6 @@ struct Codec2Client::Component : public Codec2Client::Configurable {
    void holdIgbaBlocks(
            const std::list<std::unique_ptr<C2Work>>& workList);

    // Connect to a given InputSurface.
    c2_status_t connectToInputSurface(
            const std::shared_ptr<InputSurface>& inputSurface,
            std::shared_ptr<InputSurfaceConnection>* connection);

    c2_status_t connectToOmxInputSurface(
            const sp<HGraphicBufferProducer1>& producer,
            const sp<HGraphicBufferSource>& source,
            std::shared_ptr<InputSurfaceConnection>* connection);

    c2_status_t disconnectFromInputSurface();

    c2_status_t initApexHandler(
            const std::shared_ptr<Listener> &listener,
            const std::shared_ptr<Component> &comp);
@@ -595,44 +589,78 @@ protected:
    void handleOnWorkDone(const std::list<std::unique_ptr<C2Work>> &workItems);
};


// Creation of InputSurface
// Codec2Client               --> Codec2Client::InputSurface.
// Codec2Client::InputSurface --> Codec2Client::InputSurfaceConnection
//
// Codec2Client::InputSurface could have at most only one
// Codec2Client::InputSurfaceConnection at any given time.
//
// A Codec2Client::InputSurfaceConnection is valid during a video encoder
// session. After a encoder session, the end of stream can be notified by
// Codec2Client::InputSurfaceConnection::signalEos() to the encoder.
//
// Codec2Client::InputSurfaceConnection::disconnect() will disconnect from the
// encoder and notify that it is no longer valid to Codec2Client::InputSurface.
// On disconnect() Codec2Client::InputSurface will perform clean-up, then
// Codec2Client::InputSurface is ready to re-start with a new encoder and a new
// Codec2Client::InputSurfaceConnection.

// The class holds ::aidl::android::hardware::media::c2::IInputSurface for the
// client framework.
struct Codec2Client::InputSurface : public Codec2Client::Configurable {
public:
    typedef ::android::hardware::media::c2::V1_0::IInputSurface Base;

    typedef ::android::hardware::media::c2::V1_0::IInputSurfaceConnection ConnectionBase;
    typedef ::aidl::android::hardware::media::c2::IInputSurface Base;

    typedef Codec2Client::InputSurfaceConnection Connection;
    typedef ::aidl::android::hardware::media::c2::IInputSurfaceConnection ConnectionBase;

    typedef ::android::IGraphicBufferProducer IGraphicBufferProducer;
    typedef Codec2Client::InputSurfaceConnection Connection;

    sp<IGraphicBufferProducer> getGraphicBufferProducer() const;
    // Return the window which is owned by the underlying interface.
    ANativeWindow *getNativeWindow();

    // Return the underlying IInputSurface.
    sp<Base> getHalInterface() const;
    ::ndk::SpAIBinder getHalInterface() const;

    // connect to a video encoder component.
    c2_status_t connect(
            const std::shared_ptr<Codec2Client::Component> &comp,
            std::shared_ptr<Connection> *connection);

    // base cannot be null.
    InputSurface(const sp<Base>& base);
    InputSurface(const std::shared_ptr<Base>& base);

protected:
    sp<Base> mBase;

    sp<IGraphicBufferProducer> mGraphicBufferProducer;
    std::shared_ptr<Base> mBase;

    std::once_flag mWindowInitOnce;
    ANativeWindow *mNativeWindow; // lazily initialized,
                                  // for later construction params binding.
    friend struct Codec2Client;
    friend struct Component;
};

struct Codec2Client::InputSurfaceConnection : public Codec2Client::Configurable {
// The class holds ::aidl::android::hardware::media::c2::IInputSurfaceConnection
// for the client framework.
struct Codec2Client::InputSurfaceConnection {

    typedef ::android::hardware::media::c2::V1_0::IInputSurfaceConnection Base;
    typedef ::aidl::android::hardware::media::c2::IInputSurfaceConnection Base;

    // disconnect from a video encoder from the class.
    // This will eventually notify Codec2Client::InputSurface that
    // life cycle of the class is ended.
    c2_status_t disconnect();

    // signal Eos to the connected video encoder.
    c2_status_t signalEos();

    // base cannot be null.
    InputSurfaceConnection(const sp<Base>& base);
    InputSurfaceConnection(const std::shared_ptr<Base>& base);

protected:
    sp<Base> mBase;
    std::shared_ptr<Base> mBase;

    friend struct Codec2Client::InputSurface;
};