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

Commit a5a96828 authored by Wonsik Kim's avatar Wonsik Kim
Browse files

CCodec: buffer handling refactoring

- Separated Flex/Array implementation and Input/Output interface.
- Moved wrapping/conversion into Codec2Buffer interface.
- Use Create{Linear|Graphic}Buffer where applicable.

Test: setprop debug.stagefright.ccodec yes
Test: stagefright -S -N c2.google.avc.decoder /sdcard/a.mp4
Test: stagefright -ao -N c2.google.aac.decoder /sdcard/a.mp4
Test: audioloop -N c2.google.aac.encoder -M audio/mp4a-latm
Test: screenrecord --codec-name c2.google.avc.encoder /sdcard/record.mp4
Test: screenrecord --persistent-surface --codec-name c2.google.avc.encoder /sdcard/record.mp4
Fixes: 72445205
Change-Id: I5d0e95b63770b96d22ca8fbb30d054696e58e808
parent d2ce2b80
Loading
Loading
Loading
Loading
+107 −11
Original line number Diff line number Diff line
@@ -64,10 +64,87 @@ ICrypto::DestinationType SecureBuffer::getDestinationType() {
    return ICrypto::kDestinationTypeNativeHandle;
}

// Codec2Buffer

bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const {
    if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
        return false;
    }
    if (buffer->data().type() != C2BufferData::LINEAR) {
        return false;
    }
    if (buffer->data().linearBlocks().size() == 0u) {
        // Nothing to copy, so we can copy by doing nothing.
        return true;
    } else if (buffer->data().linearBlocks().size() > 1u) {
        // We don't know how to copy more than one blocks.
        return false;
    }
    if (buffer->data().linearBlocks()[0].size() > capacity()) {
        // It won't fit.
        return false;
    }
    return true;
}

bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
    // We assume that all canCopyLinear() checks passed.
    if (buffer->data().linearBlocks().size() == 0u) {
        setRange(0, 0);
        return true;
    }
    C2ReadView view = buffer->data().linearBlocks()[0].map().get();
    if (view.error() != C2_OK) {
        ALOGD("Error while mapping: %d", view.error());
        return false;
    }
    if (view.capacity() > capacity()) {
        ALOGD("C2ConstLinearBlock lied --- it actually doesn't fit: view(%u) > this(%zu)",
                view.capacity(), capacity());
        return false;
    }
    memcpy(base(), view.data(), view.capacity());
    setRange(0, view.capacity());
    return true;
}

// LocalLinearBuffer

bool LocalLinearBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
    return canCopyLinear(buffer);
}

bool LocalLinearBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
    return copyLinear(buffer);
}

// DummyContainerBuffer

DummyContainerBuffer::DummyContainerBuffer(
        const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer)
    : Codec2Buffer(format, new ABuffer(nullptr, 1)),
      mBufferRef(buffer) {
    setRange(0, buffer ? 1 : 0);
}

std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
    return std::move(mBufferRef);
}

bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
    return !mBufferRef;
}

bool DummyContainerBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
    mBufferRef = buffer;
    setRange(0, mBufferRef ? 1 : 0);
    return true;
}

// LinearBlockBuffer

// static
sp<LinearBlockBuffer> LinearBlockBuffer::allocate(
sp<LinearBlockBuffer> LinearBlockBuffer::Allocate(
        const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) {
    C2WriteView writeView(block->map().get());
    if (writeView.error() != C2_OK) {
@@ -76,15 +153,23 @@ sp<LinearBlockBuffer> LinearBlockBuffer::allocate(
    return new LinearBlockBuffer(format, std::move(writeView), block);
}

C2ConstLinearBlock LinearBlockBuffer::share() {
    return mBlock->share(offset(), size(), C2Fence());
std::shared_ptr<C2Buffer> LinearBlockBuffer::asC2Buffer() {
    return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
}

bool LinearBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
    return canCopyLinear(buffer);
}

bool LinearBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
    return copyLinear(buffer);
}

LinearBlockBuffer::LinearBlockBuffer(
        const sp<AMessage> &format,
        C2WriteView&& writeView,
        const std::shared_ptr<C2LinearBlock> &block)
    : MediaCodecBuffer(format, new ABuffer(writeView.data(), writeView.size())),
    : Codec2Buffer(format, new ABuffer(writeView.data(), writeView.size())),
      mWriteView(writeView),
      mBlock(block) {
}
@@ -92,23 +177,34 @@ LinearBlockBuffer::LinearBlockBuffer(
// ConstLinearBlockBuffer

// static
sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::allocate(
        const sp<AMessage> &format, const C2ConstLinearBlock &block) {
    C2ReadView readView(block.map().get());
sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::Allocate(
        const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) {
    if (!buffer
            || buffer->data().type() != C2BufferData::LINEAR
            || buffer->data().linearBlocks().size() != 1u) {
        return nullptr;
    }
    C2ReadView readView(buffer->data().linearBlocks()[0].map().get());
    if (readView.error() != C2_OK) {
        return nullptr;
    }
    return new ConstLinearBlockBuffer(format, std::move(readView));
    return new ConstLinearBlockBuffer(format, std::move(readView), buffer);
}

ConstLinearBlockBuffer::ConstLinearBlockBuffer(
        const sp<AMessage> &format,
        C2ReadView&& readView)
    : MediaCodecBuffer(format, new ABuffer(
        C2ReadView&& readView,
        const std::shared_ptr<C2Buffer> &buffer)
    : Codec2Buffer(format, new ABuffer(
            // NOTE: ABuffer only takes non-const pointer but this data is
            //       supposed to be read-only.
            const_cast<uint8_t *>(readView.data()), readView.capacity())),
      mReadView(readView) {
      mReadView(readView),
      mBufferRef(buffer) {
}

std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
    return std::move(mBufferRef);
}

}  // namespace android
+294 −310

File changed.

Preview size limit exceeded, changes collapsed.

+3 −24
Original line number Diff line number Diff line
@@ -366,26 +366,6 @@ void SimpleC2Component::processQueue() {
    }
}

namespace {

class GraphicBuffer : public C2Buffer {
public:
    GraphicBuffer(
            const std::shared_ptr<C2GraphicBlock> &block,
            const C2Rect &crop)
        : C2Buffer({ block->share(crop, ::android::C2Fence()) }) {}
};


class LinearBuffer : public C2Buffer {
public:
    LinearBuffer(
            const std::shared_ptr<C2LinearBlock> &block, size_t offset, size_t size)
        : C2Buffer({ block->share(offset, size, ::android::C2Fence()) }) {}
};

}  // namespace

std::shared_ptr<C2Buffer> SimpleC2Component::createLinearBuffer(
        const std::shared_ptr<C2LinearBlock> &block) {
    return createLinearBuffer(block, block->offset(), block->size());
@@ -393,7 +373,7 @@ std::shared_ptr<C2Buffer> SimpleC2Component::createLinearBuffer(

std::shared_ptr<C2Buffer> SimpleC2Component::createLinearBuffer(
        const std::shared_ptr<C2LinearBlock> &block, size_t offset, size_t size) {
    return std::make_shared<LinearBuffer>(block, offset, size);
    return C2Buffer::CreateLinearBuffer(block->share(offset, size, ::android::C2Fence()));
}

std::shared_ptr<C2Buffer> SimpleC2Component::createGraphicBuffer(
@@ -402,9 +382,8 @@ std::shared_ptr<C2Buffer> SimpleC2Component::createGraphicBuffer(
}

std::shared_ptr<C2Buffer> SimpleC2Component::createGraphicBuffer(
        const std::shared_ptr<C2GraphicBlock> &block,
        const C2Rect &crop) {
    return std::make_shared<GraphicBuffer>(block, crop);
        const std::shared_ptr<C2GraphicBlock> &block, const C2Rect &crop) {
    return C2Buffer::CreateGraphicBuffer(block->share(crop, ::android::C2Fence()));
}

} // namespace android
+97 −7
Original line number Diff line number Diff line
@@ -24,17 +24,100 @@

namespace android {

class Codec2Buffer : public MediaCodecBuffer {
public:
    using MediaCodecBuffer::MediaCodecBuffer;
    ~Codec2Buffer() override = default;

    /**
     * \return  C2Buffer object represents this buffer.
     */
    virtual std::shared_ptr<C2Buffer> asC2Buffer() = 0;

    /**
     * Test if we can copy the content of |buffer| into this object.
     *
     * \param   buffer  C2Buffer object to copy.
     * \return  true    if the content of buffer can be copied over to this buffer
     *          false   otherwise.
     */
    virtual bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
        (void)buffer;
        return false;
    }

    /**
     * Copy the content of |buffer| into this object. This method assumes that
     * canCopy() check already passed.
     *
     * \param   buffer  C2Buffer object to copy.
     * \return  true    if successful
     *          false   otherwise.
     */
    virtual bool copy(const std::shared_ptr<C2Buffer> &buffer) {
        (void)buffer;
        return false;
    }

protected:
    /**
     * canCopy() implementation for linear buffers.
     */
    bool canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const;

    /**
     * copy() implementation for linear buffers.
     */
    bool copyLinear(const std::shared_ptr<C2Buffer> &buffer);
};

/**
 * MediaCodecBuffer implementation on top of local linear buffer. This cannot
 * cross process boundary so asC2Buffer() returns only nullptr.
 */
class LocalLinearBuffer : public Codec2Buffer {
public:
    using Codec2Buffer::Codec2Buffer;

    std::shared_ptr<C2Buffer> asC2Buffer() override { return nullptr; }
    bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const override;
    bool copy(const std::shared_ptr<C2Buffer> &buffer) override;
};

/**
 * MediaCodecBuffer implementation to be used only as a dummy wrapper around a
 * C2Buffer object.
 */
class DummyContainerBuffer : public Codec2Buffer {
public:
    DummyContainerBuffer(
            const sp<AMessage> &format,
            const std::shared_ptr<C2Buffer> &buffer = nullptr);

    std::shared_ptr<C2Buffer> asC2Buffer() override;
    bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const override;
    bool copy(const std::shared_ptr<C2Buffer> &buffer) override;

private:
    std::shared_ptr<C2Buffer> mBufferRef;
};

/**
 * MediaCodecBuffer implementation wraps around C2LinearBlock.
 */
class LinearBlockBuffer : public MediaCodecBuffer {
class LinearBlockBuffer : public Codec2Buffer {
public:
    static sp<LinearBlockBuffer> allocate(
    /**
     * Allocate a new LinearBufferBlock wrapping around C2LinearBlock object.
     */
    static sp<LinearBlockBuffer> Allocate(
            const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block);

    virtual ~LinearBlockBuffer() = default;

    C2ConstLinearBlock share();
    std::shared_ptr<C2Buffer> asC2Buffer() override;
    bool canCopy(const std::shared_ptr<C2Buffer> &buffer) const override;
    bool copy(const std::shared_ptr<C2Buffer> &buffer) override;

private:
    LinearBlockBuffer(
@@ -50,20 +133,27 @@ private:
/**
 * MediaCodecBuffer implementation wraps around C2ConstLinearBlock.
 */
class ConstLinearBlockBuffer : public MediaCodecBuffer {
class ConstLinearBlockBuffer : public Codec2Buffer {
public:
    static sp<ConstLinearBlockBuffer> allocate(
            const sp<AMessage> &format, const C2ConstLinearBlock &block);
    /**
     * Allocate a new ConstLinearBlockBuffer wrapping around C2Buffer object.
     */
    static sp<ConstLinearBlockBuffer> Allocate(
            const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer);

    virtual ~ConstLinearBlockBuffer() = default;

    std::shared_ptr<C2Buffer> asC2Buffer() override;

private:
    ConstLinearBlockBuffer(
            const sp<AMessage> &format,
            C2ReadView &&readView);
            C2ReadView &&readView,
            const std::shared_ptr<C2Buffer> &buffer);
    ConstLinearBlockBuffer() = delete;

    C2ReadView mReadView;
    std::shared_ptr<C2Buffer> mBufferRef;
};

}  // namespace android