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

Commit c66fe0cf authored by Lubin Yin's avatar Lubin Yin
Browse files

codec2: Add android fence implementation for C2Fence

Add a new C2Fence implementation that wraps a android fence, which is
based on linux sync file and can be transported through IPC.

Test: Camera and YouTube
Bug: 222463114
Change-Id: I14f66e6f4cf4ff3c878a3d8e78988c50d72c9a21
Merged-in: I14f66e6f4cf4ff3c878a3d8e78988c50d72c9a21
parent 86fa4873
Loading
Loading
Loading
Loading
+9 −12
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@
#include <C2BlockInternal.h>
#include <C2BlockInternal.h>
#include <C2Buffer.h>
#include <C2Buffer.h>
#include <C2Component.h>
#include <C2Component.h>
#include <C2FenceFactory.h>
#include <C2Param.h>
#include <C2Param.h>
#include <C2ParamInternal.h>
#include <C2ParamInternal.h>
#include <C2PlatformSupport.h>
#include <C2PlatformSupport.h>
@@ -759,17 +760,14 @@ bool addBaseBlock(
// Note: File descriptors are not duplicated. The original file descriptor must
// Note: File descriptors are not duplicated. The original file descriptor must
// not be closed before the transaction is complete.
// not be closed before the transaction is complete.
bool objcpy(hidl_handle* d, const C2Fence& s) {
bool objcpy(hidl_handle* d, const C2Fence& s) {
    (void)s; // TODO: implement s.fd()
    int fenceFd = -1;
    d->setTo(nullptr);
    d->setTo(nullptr);
    if (fenceFd >= 0) {
    native_handle_t* handle = _C2FenceFactory::CreateNativeHandle(s);
        native_handle_t *handle = native_handle_create(1, 0);
    if (handle) {
        if (!handle) {
            LOG(ERROR) << "Failed to create a native handle.";
            return false;
        }
        handle->data[0] = fenceFd;
        d->setTo(handle, true /* owns */);
        d->setTo(handle, true /* owns */);
//  } else if (!s.ready()) {
//      // TODO: we should wait for unmarshallable fences but this may not be
//      // the best place for it. We can safely ignore here as at this time
//      // all fences used here are marshallable.
    }
    }
    return true;
    return true;
}
}
@@ -1184,9 +1182,8 @@ struct C2BaseBlock {
// Note: File descriptors are not duplicated. The original file descriptor must
// Note: File descriptors are not duplicated. The original file descriptor must
// not be closed before the transaction is complete.
// not be closed before the transaction is complete.
bool objcpy(C2Fence* d, const hidl_handle& s) {
bool objcpy(C2Fence* d, const hidl_handle& s) {
    // TODO: Implement.
    const native_handle_t* handle = s.getNativeHandle();
    (void)s;
    *d = _C2FenceFactory::CreateFromNativeHandle(handle);
    *d = C2Fence();
    return true;
    return true;
}
}


+14 −1
Original line number Original line Diff line number Diff line
@@ -880,6 +880,19 @@ status_t CCodecBufferChannel::renderOutputBuffer(
        return UNKNOWN_ERROR;
        return UNKNOWN_ERROR;
    }
    }
    const C2ConstGraphicBlock &block = blocks.front();
    const C2ConstGraphicBlock &block = blocks.front();
    C2Fence c2fence = block.fence();
    sp<Fence> fence = Fence::NO_FENCE;
    // TODO: it's not sufficient to just check isHW() and then construct android::fence from it.
    // Once C2Fence::type() is added, check the exact C2Fence type
    if (c2fence.isHW()) {
        int fenceFd = c2fence.fd();
        fence = sp<Fence>::make(fenceFd);
        if (!fence) {
            ALOGE("[%s] Failed to allocate a fence", mName);
            close(fenceFd);
            return NO_MEMORY;
        }
    }


    // TODO: revisit this after C2Fence implementation.
    // TODO: revisit this after C2Fence implementation.
    android::IGraphicBufferProducer::QueueBufferInput qbi(
    android::IGraphicBufferProducer::QueueBufferInput qbi(
@@ -892,7 +905,7 @@ status_t CCodecBufferChannel::renderOutputBuffer(
                 blocks.front().crop().bottom()),
                 blocks.front().crop().bottom()),
            videoScalingMode,
            videoScalingMode,
            transform,
            transform,
            Fence::NO_FENCE, 0);
            fence, 0);
    if (hdrStaticInfo || hdrDynamicInfo) {
    if (hdrStaticInfo || hdrDynamicInfo) {
        HdrMetadata hdr;
        HdrMetadata hdr;
        if (hdrStaticInfo) {
        if (hdrStaticInfo) {
+153 −0
Original line number Original line Diff line number Diff line
@@ -16,13 +16,24 @@


//#define LOG_NDEBUG 0
//#define LOG_NDEBUG 0
#define LOG_TAG "C2FenceFactory"
#define LOG_TAG "C2FenceFactory"
#include <cutils/native_handle.h>
#include <utils/Log.h>
#include <utils/Log.h>
#include <ui/Fence.h>


#include <C2FenceFactory.h>
#include <C2FenceFactory.h>
#include <C2SurfaceSyncObj.h>
#include <C2SurfaceSyncObj.h>


#define MAX_FENCE_FDS 1

class C2Fence::Impl {
class C2Fence::Impl {
public:
public:
    enum type_t : uint32_t {
        INVALID_FENCE,
        NULL_FENCE,
        SURFACE_FENCE,
        SYNC_FENCE,
    };

    virtual c2_status_t wait(c2_nsecs_t timeoutNs) = 0;
    virtual c2_status_t wait(c2_nsecs_t timeoutNs) = 0;


    virtual bool valid() const = 0;
    virtual bool valid() const = 0;
@@ -33,9 +44,26 @@ public:


    virtual bool isHW() const = 0;
    virtual bool isHW() const = 0;


    virtual type_t type() const = 0;

    /**
     * Create a native handle for the fence so it can be marshalled.
     * The native handle must store fence type in the first integer.
     *
     * \return a valid native handle if the fence can be marshalled, otherwise return null.
     */
    virtual native_handle_t *createNativeHandle() const = 0;

    virtual ~Impl() = default;
    virtual ~Impl() = default;


    Impl() = default;
    Impl() = default;

    static type_t GetTypeFromNativeHandle(const native_handle_t* nh) {
        if (nh && nh->numFds >= 0 && nh->numFds <= MAX_FENCE_FDS && nh->numInts > 0) {
            return static_cast<type_t>(nh->data[nh->numFds]);
        }
        return INVALID_FENCE;
    }
};
};


c2_status_t C2Fence::wait(c2_nsecs_t timeoutNs) {
c2_status_t C2Fence::wait(c2_nsecs_t timeoutNs) {
@@ -115,6 +143,15 @@ public:
        return false;
        return false;
    }
    }


    virtual type_t type() const {
        return SURFACE_FENCE;
    }

    virtual native_handle_t *createNativeHandle() const {
        ALOG_ASSERT(false, "Cannot create native handle from surface fence");
        return nullptr;
    }

    virtual ~SurfaceFenceImpl() {};
    virtual ~SurfaceFenceImpl() {};


    SurfaceFenceImpl(std::shared_ptr<C2SurfaceSyncMemory> syncMem, uint32_t waitId) :
    SurfaceFenceImpl(std::shared_ptr<C2SurfaceSyncMemory> syncMem, uint32_t waitId) :
@@ -143,3 +180,119 @@ C2Fence _C2FenceFactory::CreateSurfaceFence(
    }
    }
    return C2Fence();
    return C2Fence();
}
}

using namespace android;

class _C2FenceFactory::SyncFenceImpl : public C2Fence::Impl {
public:
    virtual c2_status_t wait(c2_nsecs_t timeoutNs) {
        c2_nsecs_t timeoutMs = timeoutNs / 1000;
        if (timeoutMs > INT_MAX) {
            timeoutMs = INT_MAX;
        }

        switch (mFence->wait((int)timeoutMs)) {
            case NO_ERROR:
                return C2_OK;
            case -ETIME:
                return C2_TIMED_OUT;
            default:
                return C2_CORRUPTED;
        }
    }

    virtual bool valid() const {
        return mFence->getStatus() != Fence::Status::Invalid;
    }

    virtual bool ready() const {
        return mFence->getStatus() == Fence::Status::Signaled;
    }

    virtual int fd() const {
        return mFence->dup();
    }

    virtual bool isHW() const {
        return true;
    }

    virtual type_t type() const {
        return SYNC_FENCE;
    }

    virtual native_handle_t *createNativeHandle() const {
        native_handle_t* nh = native_handle_create(1, 1);
        if (!nh) {
            ALOGE("Failed to allocate native handle for sync fence");
            return nullptr;
        }
        nh->data[0] = fd();
        nh->data[1] = type();
        return nh;
    }

    virtual ~SyncFenceImpl() {};

    SyncFenceImpl(int fenceFd) :
            mFence(sp<Fence>::make(fenceFd)) {}

    static std::shared_ptr<SyncFenceImpl> CreateFromNativeHandle(const native_handle_t* nh) {
        if (!nh || nh->numFds != 1 || nh->numInts != 1) {
            ALOGE("Invalid handle for sync fence");
            return nullptr;
        }
        int fd = dup(nh->data[0]);
        std::shared_ptr<SyncFenceImpl> p = std::make_shared<SyncFenceImpl>(fd);
        if (!p) {
            ALOGE("Failed to allocate sync fence impl");
            close(fd);
        }
        return p;
    }

private:
    const sp<Fence> mFence;
};

C2Fence _C2FenceFactory::CreateSyncFence(int fenceFd) {
    std::shared_ptr<C2Fence::Impl> p;
    if (fenceFd >= 0) {
        p = std::make_shared<_C2FenceFactory::SyncFenceImpl>(fenceFd);
        if (!p) {
            ALOGE("Failed to allocate sync fence impl");
            close(fenceFd);
        }
        if (!p->valid()) {
            p.reset();
        }
    } else {
        ALOGE("Create sync fence from invalid fd");
    }
    return C2Fence(p);
}

native_handle_t* _C2FenceFactory::CreateNativeHandle(const C2Fence& fence) {
    return fence.mImpl? fence.mImpl->createNativeHandle() : nullptr;
}

C2Fence _C2FenceFactory::CreateFromNativeHandle(const native_handle_t* handle) {
    if (!handle) {
        return C2Fence();
    }
    C2Fence::Impl::type_t type = C2Fence::Impl::GetTypeFromNativeHandle(handle);
    std::shared_ptr<C2Fence::Impl> p;
    switch (type) {
        case C2Fence::Impl::SYNC_FENCE:
            p = SyncFenceImpl::CreateFromNativeHandle(handle);
            break;
        default:
            ALOGW("Unsupported fence type %d", type);
            break;
    }
    if (p && !p->valid()) {
        p.reset();
    }
    return C2Fence(p);
}
+25 −0
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@ class C2SurfaceSyncMemory;
struct _C2FenceFactory {
struct _C2FenceFactory {


    class SurfaceFenceImpl;
    class SurfaceFenceImpl;
    class SyncFenceImpl;


    /*
    /*
     * Create C2Fence for BufferQueueBased blockpool.
     * Create C2Fence for BufferQueueBased blockpool.
@@ -38,6 +39,30 @@ struct _C2FenceFactory {
    static C2Fence CreateSurfaceFence(
    static C2Fence CreateSurfaceFence(
            std::shared_ptr<C2SurfaceSyncMemory> syncMem,
            std::shared_ptr<C2SurfaceSyncMemory> syncMem,
            uint32_t waitId);
            uint32_t waitId);

    /*
     * Create C2Fence from a fence file fd.
     *
     * \param fenceFd           Fence file descriptor.
     *                          It will be owned and closed by the returned fence object.
     */
    static C2Fence CreateSyncFence(int fenceFd);

    /**
     * Create a native handle from fence for marshalling
     *
     * \return a non-null pointer if the fence can be marshalled, otherwise return nullptr
     */
    static native_handle_t* CreateNativeHandle(const C2Fence& fence);

    /*
     * Create C2Fence from a native handle.

     * \param handle           A native handle representing a fence
     *                         The fd in the native handle will be duplicated, so the caller will
     *                         still own the handle and have to close it.
     */
    static C2Fence CreateFromNativeHandle(const native_handle_t* handle);
};
};