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

Commit 56d65dc0 authored by Wei Jia's avatar Wei Jia Committed by Android (Google) Code Review
Browse files

Merge "IMediaSource: use shared memory to transfer large buffer." into nyc-dev

parents c3ed9d0c e9a5b96e
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ namespace android {
struct MediaSource;
class MetaData;
class MediaBuffer;
class MediaBufferGroup;

class IMediaSource : public IInterface {
public:
@@ -112,6 +113,8 @@ public:
class BnMediaSource: public BnInterface<IMediaSource>
{
public:
    BnMediaSource();

    virtual status_t    onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                uint32_t flags = 0);

@@ -122,6 +125,12 @@ public:
    virtual status_t setBuffers(const Vector<MediaBuffer *> & /* buffers */) {
        return ERROR_UNSUPPORTED;
    }

protected:
    virtual ~BnMediaSource();

private:
    MediaBufferGroup *mGroup;
};


+3 −0
Original line number Diff line number Diff line
@@ -48,6 +48,9 @@ private:

class MediaBuffer : public MediaBufferBase {
public:
    // allocations larger than or equal to this will use shared memory.
    static const size_t kSharedMemThreshold = 64 * 1024;

    // The underlying data remains the responsibility of the caller!
    MediaBuffer(void *data, size_t size);

+5 −1
Original line number Diff line number Diff line
@@ -39,7 +39,11 @@ public:
    // The returned buffer will have a reference count of 1.
    // If nonBlocking is true and a buffer is not immediately available,
    // buffer is set to NULL and it returns WOULD_BLOCK.
    status_t acquire_buffer(MediaBuffer **buffer, bool nonBlocking = false);
    // If requestedSize is 0, any free MediaBuffer will be returned.
    // If requestedSize is > 0, the returned MediaBuffer should have buffer
    // size of at least requstedSize.
    status_t acquire_buffer(
            MediaBuffer **buffer, bool nonBlocking = false, size_t requestedSize = 0);

protected:
    virtual void signalBufferReturned(MediaBuffer *buffer);
+50 −7
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <binder/Parcel.h>
#include <media/IMediaSource.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>

@@ -47,8 +48,9 @@ enum {

class RemoteMediaBufferReleaser : public BBinder {
public:
    RemoteMediaBufferReleaser(MediaBuffer *buf) {
    RemoteMediaBufferReleaser(MediaBuffer *buf, sp<BnMediaSource> owner) {
        mBuf = buf;
        mOwner = owner;
    }
    ~RemoteMediaBufferReleaser() {
        if (mBuf) {
@@ -70,6 +72,10 @@ public:
    }
private:
    MediaBuffer *mBuf;
    // Keep a ref to ensure MediaBuffer is released before the owner, i.e., BnMediaSource,
    // because BnMediaSource needs to delete MediaBufferGroup in its dtor and
    // MediaBufferGroup dtor requires all MediaBuffer's have 0 ref count.
    sp<BnMediaSource> mOwner;
};


@@ -207,6 +213,15 @@ IMPLEMENT_META_INTERFACE(MediaSource, "android.media.IMediaSource");
#undef LOG_TAG
#define LOG_TAG "BnMediaSource"

BnMediaSource::BnMediaSource()
    : mGroup(NULL) {
}

BnMediaSource::~BnMediaSource() {
    delete mGroup;
    mGroup = NULL;
}

status_t BnMediaSource::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
@@ -263,17 +278,45 @@ status_t BnMediaSource::onTransact(
                size_t usedSize = buf->range_length();
                // even if we're using shared memory, we might not want to use it, since for small
                // sizes it's faster to copy data through the Binder transaction
                if (buf->mMemory != NULL && usedSize >= 64 * 1024) {
                    ALOGV("buffer is using shared memory: %zu", usedSize);
                // On the other hand, if the data size is large enough, it's better to use shared
                // memory. When data is too large, binder can't handle it.
                if (usedSize >= MediaBuffer::kSharedMemThreshold) {
                    ALOGV("use shared memory: %zu", usedSize);

                    MediaBuffer *transferBuf = buf;
                    size_t offset = buf->range_offset();
                    if (transferBuf->mMemory == NULL) {
                        if (mGroup == NULL) {
                            mGroup = new MediaBufferGroup;
                            size_t allocateSize = usedSize;
                            if (usedSize < SIZE_MAX / 3) {
                                allocateSize = usedSize * 3 / 2;
                            }
                            mGroup->add_buffer(new MediaBuffer(allocateSize));
                        }

                        ret = mGroup->acquire_buffer(
                                &transferBuf, false /* nonBlocking */, usedSize);
                        if (ret != OK || transferBuf == NULL || transferBuf->mMemory == NULL) {
                            ALOGW("failed to acquire shared memory, ret %d", ret);
                            reply->writeInt32(NULL_BUFFER);
                            return NO_ERROR;
                        }
                        memcpy(transferBuf->data(), (uint8_t*)buf->data() + buf->range_offset(),
                                buf->range_length());
                        offset = 0;
                    }

                    reply->writeInt32(SHARED_BUFFER);
                    RemoteMediaBufferReleaser *wrapper = new RemoteMediaBufferReleaser(buf);
                    RemoteMediaBufferReleaser *wrapper =
                        new RemoteMediaBufferReleaser(transferBuf, this);
                    reply->writeStrongBinder(wrapper);
                    reply->writeStrongBinder(IInterface::asBinder(buf->mMemory));
                    reply->writeInt32(buf->range_offset());
                    reply->writeStrongBinder(IInterface::asBinder(transferBuf->mMemory));
                    reply->writeInt32(offset);
                    reply->writeInt32(usedSize);
                    buf->meta_data()->writeToParcel(*reply);
                } else {
                    // buffer is not in shared memory, or is small: copy it
                    // buffer is small: copy it
                    if (buf->mMemory != NULL) {
                        ALOGV("%zu shared mem available, but only %zu used", buf->mMemory->size(), buf->range_length());
                    }
+0 −1
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ LOCAL_SRC_FILES:= \
        MPEG4Extractor.cpp                \
        MPEG4Writer.cpp                   \
        MediaAdapter.cpp                  \
        MediaBufferGroup.cpp              \
        MediaClock.cpp                    \
        MediaCodec.cpp                    \
        MediaCodecList.cpp                \
Loading