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

Commit 0d231a6f authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Codec2: Move Hdr metadata set/get to vndk from ccodec" into main

parents ab3a0423 bf7fca8b
Loading
Loading
Loading
Loading
+0 −201
Original line number Diff line number Diff line
@@ -22,8 +22,6 @@

#include <android_media_codec.h>

#include <aidl/android/hardware/graphics/common/Cta861_3.h>
#include <aidl/android/hardware/graphics/common/Smpte2086.h>
#include <android-base/no_destructor.h>
#include <android-base/properties.h>
#include <android/hardware/cas/native/1.0/types.h>
@@ -38,7 +36,6 @@
#include <media/stagefright/foundation/ColorUtils.h>
#include <mediadrm/ICrypto.h>
#include <nativebase/nativebase.h>
#include <ui/GraphicBufferMapper.h>
#include <ui/Fence.h>

#include <C2AllocatorGralloc.h>
@@ -602,202 +599,4 @@ EncryptedLinearBlockBuffer::MappedBlock::~MappedBlock() {
    mView.setOffset(0);
}

using ::aidl::android::hardware::graphics::common::Cta861_3;
using ::aidl::android::hardware::graphics::common::Smpte2086;

namespace {

class GrallocBuffer {
public:
    GrallocBuffer(const C2Handle *const handle) : mBuffer(nullptr) {
        GraphicBufferMapper& mapper = GraphicBufferMapper::get();

        // Unwrap raw buffer handle from the C2Handle
        native_handle_t *nh = UnwrapNativeCodec2GrallocHandle(handle);
        if (!nh) {
            ALOGE("handle is not compatible to any gralloc C2Handle types");
            return;
        }
        // Import the raw handle so IMapper can use the buffer. The imported
        // handle must be freed when the client is done with the buffer.
        status_t status = mapper.importBufferNoValidate(
                nh,
                &mBuffer);

        if (status != OK) {
            ALOGE("Failed to import buffer. Status: %d.", status);
            return;
        }

        // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
        //         does not clone the fds. Thus we need to delete the handle
        //         without closing it.
        native_handle_delete(nh);
    }

    ~GrallocBuffer() {
        GraphicBufferMapper& mapper = GraphicBufferMapper::get();
        if (mBuffer) {
            // Free the imported buffer handle. This does not release the
            // underlying buffer itself.
            mapper.freeBuffer(mBuffer);
        }
    }

    buffer_handle_t get() const { return mBuffer; }
    operator bool() const { return (mBuffer != nullptr); }
private:
    buffer_handle_t mBuffer;
};

}  // namspace

c2_status_t GetHdrMetadataFromGralloc4Handle(
        const C2Handle *const handle,
        std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
        std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
    c2_status_t err = C2_OK;
    GraphicBufferMapper& mapper = GraphicBufferMapper::get();
    GrallocBuffer buffer(handle);
    if (!buffer) {
        // Gralloc4 not supported; nothing to do
        return err;
    }
    if (staticInfo) {
        ALOGV("Grabbing static HDR info from gralloc metadata");
        staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
        memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
        (*staticInfo)->maxCll = 0;
        (*staticInfo)->maxFall = 0;

        std::optional<Smpte2086> smpte2086;
        status_t status = mapper.getSmpte2086(buffer.get(), &smpte2086);
        if (status != OK || !smpte2086) {
            err = C2_CORRUPTED;
        } else {
            if (smpte2086) {
                  (*staticInfo)->mastering.red.x    = smpte2086->primaryRed.x;
                  (*staticInfo)->mastering.red.y    = smpte2086->primaryRed.y;
                  (*staticInfo)->mastering.green.x  = smpte2086->primaryGreen.x;
                  (*staticInfo)->mastering.green.y  = smpte2086->primaryGreen.y;
                  (*staticInfo)->mastering.blue.x   = smpte2086->primaryBlue.x;
                  (*staticInfo)->mastering.blue.y   = smpte2086->primaryBlue.y;
                  (*staticInfo)->mastering.white.x  = smpte2086->whitePoint.x;
                  (*staticInfo)->mastering.white.y  = smpte2086->whitePoint.y;

                  (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
                  (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
            }
        }

        std::optional<Cta861_3> cta861_3;
        status = mapper.getCta861_3(buffer.get(), &cta861_3);
        if (status != OK || !cta861_3) {
            err = C2_CORRUPTED;
        } else {
            if (cta861_3) {
                  (*staticInfo)->maxCll   = cta861_3->maxContentLightLevel;
                  (*staticInfo)->maxFall  = cta861_3->maxFrameAverageLightLevel;
            }
        }
    }

    if (err != C2_OK) {
        staticInfo->reset();
    }

    if (dynamicInfo) {
        ALOGV("Grabbing dynamic HDR info from gralloc metadata");
        dynamicInfo->reset();
        std::optional<std::vector<uint8_t>> vec;
        status_t status = mapper.getSmpte2094_40(buffer.get(), &vec);
        if (status != OK || !vec) {
            dynamicInfo->reset();
            err = C2_CORRUPTED;
        } else {
            if (vec) {
                *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
                      vec->size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
                memcpy((*dynamicInfo)->m.data, vec->data(), vec->size());
            }
        }
    }

    return err;
}

c2_status_t SetMetadataToGralloc4Handle(
        android_dataspace_t dataSpace,
        const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
        const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
        const C2Handle *const handle) {
    c2_status_t err = C2_OK;
    GraphicBufferMapper& mapper = GraphicBufferMapper::get();
    GrallocBuffer buffer(handle);
    if (!buffer) {
        // Gralloc4 not supported; nothing to do
        return err;
    }
    // Use V0 dataspaces for Gralloc4+
    if (android::media::codec::provider_->dataspace_v0_partial()) {
        ColorUtils::convertDataSpaceToV0(dataSpace);
    }
    status_t status = mapper.setDataspace(buffer.get(), static_cast<ui::Dataspace>(dataSpace));
    if (status != OK) {
       err = C2_CORRUPTED;
    }
    if (staticInfo && *staticInfo) {
        ALOGV("Setting static HDR info as gralloc metadata");
        std::optional<Smpte2086> smpte2086 = Smpte2086{
            {staticInfo->mastering.red.x, staticInfo->mastering.red.y},
            {staticInfo->mastering.green.x, staticInfo->mastering.green.y},
            {staticInfo->mastering.blue.x, staticInfo->mastering.blue.y},
            {staticInfo->mastering.white.x, staticInfo->mastering.white.y},
            staticInfo->mastering.maxLuminance,
            staticInfo->mastering.minLuminance,
        };
        if (0.0 <= smpte2086->primaryRed.x && smpte2086->primaryRed.x <= 1.0
                && 0.0 <= smpte2086->primaryRed.y && smpte2086->primaryRed.y <= 1.0
                && 0.0 <= smpte2086->primaryGreen.x && smpte2086->primaryGreen.x <= 1.0
                && 0.0 <= smpte2086->primaryGreen.y && smpte2086->primaryGreen.y <= 1.0
                && 0.0 <= smpte2086->primaryBlue.x && smpte2086->primaryBlue.x <= 1.0
                && 0.0 <= smpte2086->primaryBlue.y && smpte2086->primaryBlue.y <= 1.0
                && 0.0 <= smpte2086->whitePoint.x && smpte2086->whitePoint.x <= 1.0
                && 0.0 <= smpte2086->whitePoint.y && smpte2086->whitePoint.y <= 1.0
                && 0.0 <= smpte2086->maxLuminance && 0.0 <= smpte2086->minLuminance) {
            status = mapper.setSmpte2086(buffer.get(), smpte2086);
            if (status != OK) {
                err = C2_CORRUPTED;
            }
        }
        std::optional<Cta861_3> cta861_3 = Cta861_3{
            staticInfo->maxCll,
            staticInfo->maxFall,
        };
        if (0.0 <= cta861_3->maxContentLightLevel && 0.0 <= cta861_3->maxFrameAverageLightLevel) {
            status = mapper.setCta861_3(buffer.get(), cta861_3);
            if (status != OK) {
                err = C2_CORRUPTED;
            }
        }
    }
    if (dynamicInfo && *dynamicInfo && dynamicInfo->flexCount() > 0) {
        ALOGV("Setting dynamic HDR info as gralloc metadata");
        if (dynamicInfo->m.type_ == C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40) {
            std::optional<std::vector<uint8_t>> smpte2094_40 = std::vector<uint8_t>();
            smpte2094_40->resize(dynamicInfo->flexCount());
            memcpy(smpte2094_40->data(), dynamicInfo->m.data, dynamicInfo->flexCount());

            status = mapper.setSmpte2094_40(buffer.get(), smpte2094_40);
            if (status != OK) {
                err = C2_CORRUPTED;
            }
        } else {
            err = C2_BAD_VALUE;
        }
    }

    return err;
}

}  // namespace android
+0 −33
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@
#define CODEC2_BUFFER_H_

#include <C2Buffer.h>
#include <C2Config.h>

#include <binder/IMemory.h>
#include <media/hardware/VideoAPI.h>
@@ -381,38 +380,6 @@ private:
    int32_t mHeapSeqNum;
};

/**
 * Get HDR metadata from Gralloc4 handle.
 *
 * \param[in]   handle      handle of the allocation
 * \param[out]  staticInfo  HDR static info to be filled. Ignored if null;
 *                          if |handle| is invalid or does not contain the metadata,
 *                          the shared_ptr is reset.
 * \param[out]  dynamicInfo HDR dynamic info to be filled. Ignored if null;
 *                          if |handle| is invalid or does not contain the metadata,
 *                          the shared_ptr is reset.
 * \return C2_OK if successful
 */
c2_status_t GetHdrMetadataFromGralloc4Handle(
        const C2Handle *const handle,
        std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
        std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo);

/**
 * Set metadata to Gralloc4 handle.
 *
 * \param[in]   dataSpace   Dataspace to set.
 * \param[in]   staticInfo  HDR static info to set. Ignored if null or invalid.
 * \param[in]   dynamicInfo HDR dynamic info to set. Ignored if null or invalid.
 * \param[out]  handle      handle of the allocation.
 * \return C2_OK if successful
 */
c2_status_t SetMetadataToGralloc4Handle(
        const android_dataspace_t dataSpace,
        const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
        const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
        const C2Handle *const handle);

}  // namespace android

#endif  // CODEC2_BUFFER_H_
+202 −0
Original line number Diff line number Diff line
@@ -20,12 +20,17 @@

#include <mutex>

#include <android_media_codec.h>

#include <aidl/android/hardware/graphics/common/Cta861_3.h>
#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
#include <aidl/android/hardware/graphics/common/Smpte2086.h>
#include <android/hardware/graphics/common/1.2/types.h>
#include <cutils/native_handle.h>
#include <drm/drm_fourcc.h>
#include <gralloctypes/Gralloc4.h>
#include <hardware/gralloc.h>
#include <media/stagefright/foundation/ColorUtils.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>
#include <ui/Rect.h>
@@ -969,6 +974,203 @@ bool MigrateNativeCodec2GrallocHandle(
    return C2HandleGralloc::MigrateNativeHandle(handle, generation, igbp_id, igbp_slot);
}

using ::aidl::android::hardware::graphics::common::Cta861_3;
using ::aidl::android::hardware::graphics::common::Smpte2086;

namespace {

class GrallocBuffer {
public:
    GrallocBuffer(const C2Handle *const handle) : mBuffer(nullptr) {
        GraphicBufferMapper& mapper = GraphicBufferMapper::get();

        // Unwrap raw buffer handle from the C2Handle
        native_handle_t *nh = UnwrapNativeCodec2GrallocHandle(handle);
        if (!nh) {
            ALOGE("handle is not compatible to any gralloc C2Handle types");
            return;
        }
        // Import the raw handle so IMapper can use the buffer. The imported
        // handle must be freed when the client is done with the buffer.
        status_t status = mapper.importBufferNoValidate(
                nh,
                &mBuffer);

        if (status != OK) {
            ALOGE("Failed to import buffer. Status: %d.", status);
            return;
        }

        // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
        //         does not clone the fds. Thus we need to delete the handle
        //         without closing it.
        native_handle_delete(nh);
    }

    ~GrallocBuffer() {
        GraphicBufferMapper& mapper = GraphicBufferMapper::get();
        if (mBuffer) {
            // Free the imported buffer handle. This does not release the
            // underlying buffer itself.
            mapper.freeBuffer(mBuffer);
        }
    }

    buffer_handle_t get() const { return mBuffer; }
    operator bool() const { return (mBuffer != nullptr); }
private:
    buffer_handle_t mBuffer;
};

}  // namspace

c2_status_t GetHdrMetadataFromGralloc4Handle(
        const C2Handle *const handle,
        std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
        std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
    c2_status_t err = C2_OK;
    GraphicBufferMapper& mapper = GraphicBufferMapper::get();
    GrallocBuffer buffer(handle);
    if (!buffer) {
        // Gralloc4 not supported; nothing to do
        return err;
    }
    if (staticInfo) {
        ALOGV("Grabbing static HDR info from gralloc metadata");
        staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
        memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
        (*staticInfo)->maxCll = 0;
        (*staticInfo)->maxFall = 0;

        std::optional<Smpte2086> smpte2086;
        status_t status = mapper.getSmpte2086(buffer.get(), &smpte2086);
        if (status != OK || !smpte2086) {
            err = C2_CORRUPTED;
        } else {
            if (smpte2086) {
                  (*staticInfo)->mastering.red.x    = smpte2086->primaryRed.x;
                  (*staticInfo)->mastering.red.y    = smpte2086->primaryRed.y;
                  (*staticInfo)->mastering.green.x  = smpte2086->primaryGreen.x;
                  (*staticInfo)->mastering.green.y  = smpte2086->primaryGreen.y;
                  (*staticInfo)->mastering.blue.x   = smpte2086->primaryBlue.x;
                  (*staticInfo)->mastering.blue.y   = smpte2086->primaryBlue.y;
                  (*staticInfo)->mastering.white.x  = smpte2086->whitePoint.x;
                  (*staticInfo)->mastering.white.y  = smpte2086->whitePoint.y;

                  (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
                  (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
            }
        }

        std::optional<Cta861_3> cta861_3;
        status = mapper.getCta861_3(buffer.get(), &cta861_3);
        if (status != OK || !cta861_3) {
            err = C2_CORRUPTED;
        } else {
            if (cta861_3) {
                  (*staticInfo)->maxCll   = cta861_3->maxContentLightLevel;
                  (*staticInfo)->maxFall  = cta861_3->maxFrameAverageLightLevel;
            }
        }
    }

    if (err != C2_OK) {
        staticInfo->reset();
    }

    if (dynamicInfo) {
        ALOGV("Grabbing dynamic HDR info from gralloc metadata");
        dynamicInfo->reset();
        std::optional<std::vector<uint8_t>> vec;
        status_t status = mapper.getSmpte2094_40(buffer.get(), &vec);
        if (status != OK || !vec) {
            dynamicInfo->reset();
            err = C2_CORRUPTED;
        } else {
            if (vec) {
                *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
                      vec->size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
                memcpy((*dynamicInfo)->m.data, vec->data(), vec->size());
            }
        }
    }

    return err;
}

c2_status_t SetMetadataToGralloc4Handle(
        android_dataspace_t dataSpace,
        const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
        const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
        const C2Handle *const handle) {
    c2_status_t err = C2_OK;
    GraphicBufferMapper& mapper = GraphicBufferMapper::get();
    GrallocBuffer buffer(handle);
    if (!buffer) {
        // Gralloc4 not supported; nothing to do
        return err;
    }
    // Use V0 dataspaces for Gralloc4+
    if (android::media::codec::provider_->dataspace_v0_partial()) {
        ColorUtils::convertDataSpaceToV0(dataSpace);
    }
    status_t status = mapper.setDataspace(buffer.get(), static_cast<ui::Dataspace>(dataSpace));
    if (status != OK) {
       err = C2_CORRUPTED;
    }
    if (staticInfo && *staticInfo) {
        ALOGV("Setting static HDR info as gralloc metadata");
        std::optional<Smpte2086> smpte2086 = Smpte2086{
            {staticInfo->mastering.red.x, staticInfo->mastering.red.y},
            {staticInfo->mastering.green.x, staticInfo->mastering.green.y},
            {staticInfo->mastering.blue.x, staticInfo->mastering.blue.y},
            {staticInfo->mastering.white.x, staticInfo->mastering.white.y},
            staticInfo->mastering.maxLuminance,
            staticInfo->mastering.minLuminance,
        };
        if (0.0 <= smpte2086->primaryRed.x && smpte2086->primaryRed.x <= 1.0
                && 0.0 <= smpte2086->primaryRed.y && smpte2086->primaryRed.y <= 1.0
                && 0.0 <= smpte2086->primaryGreen.x && smpte2086->primaryGreen.x <= 1.0
                && 0.0 <= smpte2086->primaryGreen.y && smpte2086->primaryGreen.y <= 1.0
                && 0.0 <= smpte2086->primaryBlue.x && smpte2086->primaryBlue.x <= 1.0
                && 0.0 <= smpte2086->primaryBlue.y && smpte2086->primaryBlue.y <= 1.0
                && 0.0 <= smpte2086->whitePoint.x && smpte2086->whitePoint.x <= 1.0
                && 0.0 <= smpte2086->whitePoint.y && smpte2086->whitePoint.y <= 1.0
                && 0.0 <= smpte2086->maxLuminance && 0.0 <= smpte2086->minLuminance) {
            status = mapper.setSmpte2086(buffer.get(), smpte2086);
            if (status != OK) {
                err = C2_CORRUPTED;
            }
        }
        std::optional<Cta861_3> cta861_3 = Cta861_3{
            staticInfo->maxCll,
            staticInfo->maxFall,
        };
        if (0.0 <= cta861_3->maxContentLightLevel && 0.0 <= cta861_3->maxFrameAverageLightLevel) {
            status = mapper.setCta861_3(buffer.get(), cta861_3);
            if (status != OK) {
                err = C2_CORRUPTED;
            }
        }
    }
    if (dynamicInfo && *dynamicInfo && dynamicInfo->flexCount() > 0) {
        ALOGV("Setting dynamic HDR info as gralloc metadata");
        if (dynamicInfo->m.type_ == C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40) {
            std::optional<std::vector<uint8_t>> smpte2094_40 = std::vector<uint8_t>();
            smpte2094_40->resize(dynamicInfo->flexCount());
            memcpy(smpte2094_40->data(), dynamicInfo->m.data, dynamicInfo->flexCount());

            status = mapper.setSmpte2094_40(buffer.get(), smpte2094_40);
            if (status != OK) {
                err = C2_CORRUPTED;
            }
        } else {
            err = C2_BAD_VALUE;
        }
    }

    return err;
}


class C2AllocationGralloc : public C2GraphicAllocation {
+33 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <functional>

#include <C2Buffer.h>
#include <C2Config.h>

namespace android {
// VNDK
@@ -92,6 +93,38 @@ C2Handle *WrapNativeCodec2AhwbHandle(
        uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
        uint64_t origId);

/**
 * Get HDR metadata from Gralloc4 handle.
 *
 * \param[in]   handle      handle of the allocation
 * \param[out]  staticInfo  HDR static info to be filled. Ignored if null;
 *                          if |handle| is invalid or does not contain the metadata,
 *                          the shared_ptr is reset.
 * \param[out]  dynamicInfo HDR dynamic info to be filled. Ignored if null;
 *                          if |handle| is invalid or does not contain the metadata,
 *                          the shared_ptr is reset.
 * \return C2_OK if successful
 */
c2_status_t GetHdrMetadataFromGralloc4Handle(
        const C2Handle *const handle,
        std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
        std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo);

/**
 * Set metadata to Gralloc4 handle.
 *
 * \param[in]   dataSpace   Dataspace to set.
 * \param[in]   staticInfo  HDR static info to set. Ignored if null or invalid.
 * \param[in]   dynamicInfo HDR dynamic info to set. Ignored if null or invalid.
 * \param[out]  handle      handle of the allocation.
 * \return C2_OK if successful
 */
c2_status_t SetMetadataToGralloc4Handle(
        const android_dataspace_t dataSpace,
        const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
        const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
        const C2Handle *const handle);

class C2AllocatorGralloc : public C2Allocator {
public:
    virtual id_t getId() const override;