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

Commit 8a21c019 authored by Pawin Vongmasa's avatar Pawin Vongmasa
Browse files

Modify ACodec to allow using Treble.

ACodec will connect to the Treble version of Omx if the property
"debug.treble_omx" is set to true ("1", "y", "yes", "true" or "on").

Also, fix some bugs found so far.

Test: Compiles
Bug: 31399200
Change-Id: I52b27b5f99bc1d6797d3b83b8be794ed2de9956a
parent 12eb3158
Loading
Loading
Loading
Loading
+16 −0
Original line number Original line Diff line number Diff line
@@ -41,6 +41,14 @@ class MemoryDealer;
struct DescribeColorFormat2Params;
struct DescribeColorFormat2Params;
struct DataConverter;
struct DataConverter;


// Treble shared memory
namespace hidl { namespace memory { namespace V1_0 {
struct IAllocator;
struct IMemory;
}}};
typedef hidl::memory::V1_0::IAllocator TAllocator;
typedef hidl::memory::V1_0::IMemory TMemory;

struct ACodec : public AHierarchicalStateMachine, public CodecBase {
struct ACodec : public AHierarchicalStateMachine, public CodecBase {
    ACodec();
    ACodec();


@@ -86,6 +94,12 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase {


    static status_t getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]);
    static status_t getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]);


    // Read the flag from "media.use_treble_omx", save it locally, and return
    // it.
    bool updateTrebleFlag();
    // Return the saved flag.
    bool getTrebleFlag() const;

protected:
protected:
    virtual ~ACodec();
    virtual ~ACodec();


@@ -218,6 +232,8 @@ private:
    sp<IOMX> mOMX;
    sp<IOMX> mOMX;
    sp<IOMXNode> mOMXNode;
    sp<IOMXNode> mOMXNode;
    int32_t mNodeGeneration;
    int32_t mNodeGeneration;
    bool mTrebleFlag;
    sp<TAllocator> mAllocator[2];
    sp<MemoryDealer> mDealer[2];
    sp<MemoryDealer> mDealer[2];


    bool mUsingNativeWindow;
    bool mUsingNativeWindow;
+1 −1
Original line number Original line Diff line number Diff line
@@ -166,7 +166,7 @@ OMXBuffer& OMXBuffer::operator=(OMXBuffer&& source) {
    mMem = std::move(source.mMem);
    mMem = std::move(source.mMem);
    mGraphicBuffer = std::move(source.mGraphicBuffer);
    mGraphicBuffer = std::move(source.mGraphicBuffer);
    mNativeHandle = std::move(source.mNativeHandle);
    mNativeHandle = std::move(source.mNativeHandle);
    mHidlMemory = source.mHidlMemory; // TODO(b/34093434): Use move when available
    mHidlMemory = std::move(source.mHidlMemory);
    return *this;
    return *this;
}
}


+152 −28
Original line number Original line Diff line number Diff line
@@ -46,6 +46,8 @@
#include <media/hardware/HardwareAPI.h>
#include <media/hardware/HardwareAPI.h>
#include <media/OMXBuffer.h>
#include <media/OMXBuffer.h>


#include <hidlmemory/mapping.h>

#include <OMX_AudioExt.h>
#include <OMX_AudioExt.h>
#include <OMX_VideoExt.h>
#include <OMX_VideoExt.h>
#include <OMX_Component.h>
#include <OMX_Component.h>
@@ -59,6 +61,10 @@
#include "include/SharedMemoryBuffer.h"
#include "include/SharedMemoryBuffer.h"
#include "omx/OMXUtils.h"
#include "omx/OMXUtils.h"


#include <android/hidl/memory/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include "omx/hal/1.0/utils/WOmxNode.h"

namespace android {
namespace android {


using binder::Status;
using binder::Status;
@@ -282,7 +288,9 @@ private:


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////


struct ACodec::DeathNotifier : public IBinder::DeathRecipient {
struct ACodec::DeathNotifier :
        public IBinder::DeathRecipient,
        public ::android::hardware::hidl_death_recipient {
    explicit DeathNotifier(const sp<AMessage> &notify)
    explicit DeathNotifier(const sp<AMessage> &notify)
        : mNotify(notify) {
        : mNotify(notify) {
    }
    }
@@ -291,6 +299,12 @@ struct ACodec::DeathNotifier : public IBinder::DeathRecipient {
        mNotify->post();
        mNotify->post();
    }
    }


    virtual void serviceDied(
            uint64_t /* cookie */,
            const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
        mNotify->post();
    }

protected:
protected:
    virtual ~DeathNotifier() {}
    virtual ~DeathNotifier() {}


@@ -560,6 +574,8 @@ ACodec::ACodec()
    memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));
    memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));


    changeState(mUninitializedState);
    changeState(mUninitializedState);

    updateTrebleFlag();
}
}


ACodec::~ACodec() {
ACodec::~ACodec() {
@@ -811,7 +827,11 @@ status_t ACodec::setPortMode(int32_t portIndex, IOMX::PortMode mode) {
status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);


    if (getTrebleFlag()) {
        CHECK(mAllocator[portIndex] == NULL);
    } else {
        CHECK(mDealer[portIndex] == NULL);
        CHECK(mDealer[portIndex] == NULL);
    }
    CHECK(mBuffers[portIndex].isEmpty());
    CHECK(mBuffers[portIndex].isEmpty());


    status_t err;
    status_t err;
@@ -874,14 +894,26 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
                return NO_MEMORY;
                return NO_MEMORY;
            }
            }


            size_t totalSize = def.nBufferCountActual * (alignedSize + alignedConvSize);
            if (mode != IOMX::kPortModePresetSecureBuffer) {
            if (mode != IOMX::kPortModePresetSecureBuffer) {
                if (getTrebleFlag()) {
                    mAllocator[portIndex] = TAllocator::getService("ashmem");
                    if (mAllocator[portIndex] == nullptr) {
                        ALOGE("hidl allocator on port %d is null",
                                (int)portIndex);
                        return NO_MEMORY;
                    }
                } else {
                    size_t totalSize = def.nBufferCountActual *
                            (alignedSize + alignedConvSize);
                    mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
                    mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
                }
                }
            }


            const sp<AMessage> &format =
            const sp<AMessage> &format =
                    portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
                    portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
            for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
            for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
                hidl_memory hidlMemToken;
                sp<TMemory> hidlMem;
                sp<IMemory> mem;
                sp<IMemory> mem;


                BufferInfo info;
                BufferInfo info;
@@ -902,31 +934,87 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
                            ? new SecureBuffer(format, ptr, bufSize)
                            ? new SecureBuffer(format, ptr, bufSize)
                            : new SecureBuffer(format, native_handle, bufSize);
                            : new SecureBuffer(format, native_handle, bufSize);
                    info.mCodecData = info.mData;
                    info.mCodecData = info.mData;
                } else {
                    if (getTrebleFlag()) {
                        bool success;
                        auto transStatus = mAllocator[portIndex]->allocate(
                                bufSize,
                                [&success, &hidlMemToken](
                                        bool s,
                                        hidl_memory const& m) {
                                    success = s;
                                    hidlMemToken = m;
                                });

                        if (!transStatus.isOk()) {
                            ALOGE("hidl's AshmemAllocator failed at the "
                                    "transport: %s",
                                    transStatus.description().c_str());
                            return NO_MEMORY;
                        }
                        if (!success) {
                            return NO_MEMORY;
                        }
                        hidlMem = mapMemory(hidlMemToken);

                        err = mOMXNode->useBuffer(
                                portIndex, hidlMemToken, &info.mBufferID);
                    } else {
                    } else {
                        mem = mDealer[portIndex]->allocate(bufSize);
                        mem = mDealer[portIndex]->allocate(bufSize);
                        if (mem == NULL || mem->pointer() == NULL) {
                        if (mem == NULL || mem->pointer() == NULL) {
                            return NO_MEMORY;
                            return NO_MEMORY;
                        }
                        }


                    err = mOMXNode->useBuffer(portIndex, mem, &info.mBufferID);
                        err = mOMXNode->useBuffer(
                                portIndex, mem, &info.mBufferID);
                    }


                    if (mode == IOMX::kPortModeDynamicANWBuffer) {
                    if (mode == IOMX::kPortModeDynamicANWBuffer) {
                        ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
                        VideoNativeMetadata* metaData = (VideoNativeMetadata*)(
                                getTrebleFlag() ?
                                (void*)hidlMem->getPointer() : mem->pointer());
                        metaData->nFenceFd = -1;
                    }
                    }


                    info.mCodecData = new SharedMemoryBuffer(format, mem);
                    if (getTrebleFlag()) {
                        info.mCodecData = new SharedMemoryBuffer(
                                format, hidlMem);
                        info.mCodecRef = hidlMem;
                    } else {
                        info.mCodecData = new SharedMemoryBuffer(
                                format, mem);
                        info.mCodecRef = mem;
                        info.mCodecRef = mem;
                    }


                    // if we require conversion, allocate conversion buffer for client use;
                    // if we require conversion, allocate conversion buffer for client use;
                    // otherwise, reuse codec buffer
                    // otherwise, reuse codec buffer
                    if (mConverter[portIndex] != NULL) {
                    if (mConverter[portIndex] != NULL) {
                        CHECK_GT(conversionBufferSize, (size_t)0);
                        CHECK_GT(conversionBufferSize, (size_t)0);
                        mem = mDealer[portIndex]->allocate(conversionBufferSize);
                        if (getTrebleFlag()) {
                            bool success;
                            mAllocator[portIndex]->allocate(
                                    conversionBufferSize,
                                    [&success, &hidlMemToken](
                                            bool s,
                                            hidl_memory const& m) {
                                        success = s;
                                        hidlMemToken = m;
                                    });
                            if (!success) {
                                return NO_MEMORY;
                            }
                            hidlMem = mapMemory(hidlMemToken);
                            info.mData = new SharedMemoryBuffer(format, hidlMem);
                            info.mMemRef = hidlMem;
                        } else {
                            mem = mDealer[portIndex]->allocate(
                                    conversionBufferSize);
                            if (mem == NULL|| mem->pointer() == NULL) {
                            if (mem == NULL|| mem->pointer() == NULL) {
                                return NO_MEMORY;
                                return NO_MEMORY;
                            }
                            }
                            info.mData = new SharedMemoryBuffer(format, mem);
                            info.mData = new SharedMemoryBuffer(format, mem);
                            info.mMemRef = mem;
                            info.mMemRef = mem;
                        }
                    } else {
                    } else {
                        info.mData = info.mCodecData;
                        info.mData = info.mCodecData;
                        info.mMemRef = info.mCodecRef;
                        info.mMemRef = info.mCodecRef;
@@ -1458,8 +1546,11 @@ status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
        }
        }
    }
    }


    // clear mDealer even on an error
    if (getTrebleFlag()) {
        mAllocator[portIndex].clear();
    } else {
        mDealer[portIndex].clear();
        mDealer[portIndex].clear();
    }
    return err;
    return err;
}
}


@@ -6041,9 +6132,17 @@ void ACodec::UninitializedState::stateEntered() {


    if (mDeathNotifier != NULL) {
    if (mDeathNotifier != NULL) {
        if (mCodec->mOMXNode != NULL) {
        if (mCodec->mOMXNode != NULL) {
            if (mCodec->getTrebleFlag()) {
                auto tOmxNode =
                        (static_cast<
                        ::android::hardware::media::omx::V1_0::utils::
                        LWOmxNode*>(mCodec->mOMXNode.get()))->mBase;
                tOmxNode->unlinkToDeath(mDeathNotifier);
            } else {
                sp<IBinder> binder = IInterface::asBinder(mCodec->mOMXNode);
                sp<IBinder> binder = IInterface::asBinder(mCodec->mOMXNode);
                binder->unlinkToDeath(mDeathNotifier);
                binder->unlinkToDeath(mDeathNotifier);
            }
            }
        }
        mDeathNotifier.clear();
        mDeathNotifier.clear();
    }
    }


@@ -6130,7 +6229,8 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
    CHECK(mCodec->mOMXNode == NULL);
    CHECK(mCodec->mOMXNode == NULL);


    OMXClient client;
    OMXClient client;
    if (client.connect() != OK) {
    if ((mCodec->updateTrebleFlag() ?
            client.connectTreble() : client.connect()) != OK) {
        mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
        mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
        return false;
        return false;
    }
    }
@@ -6202,11 +6302,19 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
    }
    }


    mDeathNotifier = new DeathNotifier(notify);
    mDeathNotifier = new DeathNotifier(notify);
    if (mCodec->getTrebleFlag()) {
        auto tOmxNode = (static_cast<::android::hardware::media::omx::V1_0::
                utils::LWOmxNode*>(omxNode.get()))->mBase;
        if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) {
            mDeathNotifier.clear();
        }
    } else {
        if (IInterface::asBinder(omxNode)->linkToDeath(mDeathNotifier) != OK) {
        if (IInterface::asBinder(omxNode)->linkToDeath(mDeathNotifier) != OK) {
            // This was a local binder, if it dies so do we, we won't care
            // This was a local binder, if it dies so do we, we won't care
            // about any notifications in the afterlife.
            // about any notifications in the afterlife.
            mDeathNotifier.clear();
            mDeathNotifier.clear();
        }
        }
    }


    notify = new AMessage(kWhatOMXMessageList, mCodec);
    notify = new AMessage(kWhatOMXMessageList, mCodec);
    notify->setInt32("generation", ++mCodec->mNodeGeneration);
    notify->setInt32("generation", ++mCodec->mNodeGeneration);
@@ -7180,9 +7288,13 @@ bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
                    ALOGE("disabled port should be empty, but has %zu buffers",
                    ALOGE("disabled port should be empty, but has %zu buffers",
                            mCodec->mBuffers[kPortIndexOutput].size());
                            mCodec->mBuffers[kPortIndexOutput].size());
                    err = FAILED_TRANSACTION;
                    err = FAILED_TRANSACTION;
                } else {
                    if (mCodec->getTrebleFlag()) {
                        mCodec->mAllocator[kPortIndexOutput].clear();
                    } else {
                    } else {
                        mCodec->mDealer[kPortIndexOutput].clear();
                        mCodec->mDealer[kPortIndexOutput].clear();
                    }
                    }
                }


                if (err == OK) {
                if (err == OK) {
                    err = mCodec->mOMXNode->sendCommand(
                    err = mCodec->mOMXNode->sendCommand(
@@ -7564,7 +7676,8 @@ status_t ACodec::queryCapabilities(
    }
    }


    OMXClient client;
    OMXClient client;
    status_t err = client.connect();
    status_t err = getTrebleFlag() ?
            client.connectTreble() : client.connect();
    if (err != OK) {
    if (err != OK) {
        return err;
        return err;
    }
    }
@@ -7780,4 +7893,15 @@ status_t ACodec::getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE
    return OK;
    return OK;
}
}


bool ACodec::updateTrebleFlag() {
    mTrebleFlag = bool(property_get_bool("debug.treble_omx", 0));
    ALOGV("updateTrebleFlag() returns %s",
            mTrebleFlag ? "true" : "false");
    return mTrebleFlag;
}

bool ACodec::getTrebleFlag() const {
    return mTrebleFlag;
}

}  // namespace android
}  // namespace android
+2 −0
Original line number Original line Diff line number Diff line
@@ -114,6 +114,8 @@ LOCAL_SHARED_LIBRARIES += \
        libdl \
        libdl \
        libRScpp \
        libRScpp \
        libhidlbase \
        libhidlbase \
        libhidlmemory \
        android.hidl.memory@1.0 \
        android.hardware.media.omx@1.0 \
        android.hardware.media.omx@1.0 \
        android.hardware.media.omx@1.0-utils \
        android.hardware.media.omx@1.0-utils \


+5 −0
Original line number Original line Diff line number Diff line
@@ -34,6 +34,11 @@ SharedMemoryBuffer::SharedMemoryBuffer(const sp<AMessage> &format, const sp<IMem
      mMemory(mem) {
      mMemory(mem) {
}
}


SharedMemoryBuffer::SharedMemoryBuffer(const sp<AMessage> &format, const sp<TMemory> &mem)
    : MediaCodecBuffer(format, new ABuffer(mem->getPointer(), mem->getSize())),
      mTMemory(mem) {
}

SecureBuffer::SecureBuffer(const sp<AMessage> &format, const void *ptr, size_t size)
SecureBuffer::SecureBuffer(const sp<AMessage> &format, const void *ptr, size_t size)
    : MediaCodecBuffer(format, new ABuffer(nullptr, size)),
    : MediaCodecBuffer(format, new ABuffer(nullptr, size)),
      mPointer(ptr) {
      mPointer(ptr) {
Loading