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

Commit b1f8c266 authored by Pannag Sanketi's avatar Pannag Sanketi
Browse files

Adding Metadata mode to SurfaceMediaSource

SurfaceMediaSource operates in metadata mode only, i.e. just the
metadata is stored in videobuffers. SurfaceMediaSource passes the Gralloc
buffer handle along with a 4 byte 'type' (indicating that the metadata
is of type GrallocSource) to the encoder as opposed to the
GrallocBuffer itself.

Related to bug id: 4529323

Change-Id: I83aebc0dd10f317658cdf70be5802dfc35a1e72d
parent 897e27bc
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -69,6 +69,16 @@ typedef enum {
     * kMetadataBufferTypeGrallocSource is used to indicate that
     * the payload of the metadata buffers can be interpreted as
     * a buffer_handle_t.
     * So in this case,the metadata that the encoder receives
     * will have a byte stream that consists of two parts:
     * 1. First, there is an integer indicating that it is a GRAlloc
     * source (kMetadataBufferTypeGrallocSource)
     * 2. This is followed by the buffer_handle_t that is a handle to the
     * GRalloc buffer. The encoder needs to interpret this GRalloc handle
     * and encode the frames.
     * --------------------------------------------------------------
     * |  kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
     * --------------------------------------------------------------
     */
    kMetadataBufferTypeGrallocSource = 1,

+5 −1
Original line number Diff line number Diff line
@@ -63,6 +63,10 @@ public:
            MediaBuffer **buffer, const ReadOptions *options = NULL);
    virtual sp<MetaData> getFormat();

    // Pass the metadata over to the buffer, call when you have the lock
    void passMetadataBufferLocked(MediaBuffer **buffer);
    bool checkBufferMatchesSlot(int slot, MediaBuffer *buffer);

    // Get / Set the frame rate used for encoding. Default fps = 30
    status_t setFrameRate(int32_t fps) ;
    int32_t getFrameRate( ) const;
@@ -152,7 +156,7 @@ public:
    status_t setBufferCountServer(int bufferCount);

    // getTimestamp retrieves the timestamp associated with the image
    // set by the most recent call to updateFrameInfoLocked().
    // set by the most recent call to read()
    //
    // The timestamp is in nanoseconds, and is monotonically increasing. Its
    // other semantics (zero point, etc) are source-dependent and should be
+43 −7
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/openmax/OMX_IVCommon.h>
#include <media/stagefright/MetadataBufferType.h>

#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/SurfaceComposerClient.h>
@@ -715,9 +716,9 @@ status_t SurfaceMediaSource::read( MediaBuffer **buffer,
    mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer;
    mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp;

    // Pass the data to the MediaBuffer
    // TODO: Change later to pass in only the metadata
    *buffer = new MediaBuffer(mCurrentBuf);
    // Pass the data to the MediaBuffer. Pass in only the metadata
    passMetadataBufferLocked(buffer);

    (*buffer)->setObserver(this);
    (*buffer)->add_ref();
    (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp);
@@ -725,6 +726,34 @@ status_t SurfaceMediaSource::read( MediaBuffer **buffer,
    return OK;
}

// Pass the data to the MediaBuffer. Pass in only the metadata
// The metadata passed consists of two parts:
// 1. First, there is an integer indicating that it is a GRAlloc
// source (kMetadataBufferTypeGrallocSource)
// 2. This is followed by the buffer_handle_t that is a handle to the
// GRalloc buffer. The encoder needs to interpret this GRalloc handle
// and encode the frames.
// --------------------------------------------------------------
// |  kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
// --------------------------------------------------------------
// Note: Call only when you have the lock
void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) {
    LOGV("passMetadataBuffer");
    // MediaBuffer allocates and owns this data
    MediaBuffer *tempBuffer =
        new MediaBuffer(4 + sizeof(buffer_handle_t));
    char *data = (char *)tempBuffer->data();
    if (data == NULL) {
        LOGE("Cannot allocate memory for passing buffer metadata!");
        return;
    }
    OMX_U32 type = kMetadataBufferTypeGrallocSource;
    memcpy(data, &type, 4);
    memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t));
    *buffer = tempBuffer;
}


void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
    LOGV("signalBufferReturned");

@@ -732,14 +761,13 @@ void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
    Mutex::Autolock autoLock(mMutex);

    if (!mStarted) {
        LOGV("started = false. Nothing to do");
        LOGW("signalBufferReturned: mStarted = false! Nothing to do!");
        return;
    }

    for (Fifo::iterator it = mQueue.begin(); it != mQueue.end(); ++it) {
        if (mSlots[*it].mGraphicBuffer  ==  buffer->graphicBuffer()) {
            LOGV("Buffer %d returned. Setting it 'FREE'. New Queue size = %d",
                    *it, mQueue.size()-1);
        CHECK(mSlots[*it].mGraphicBuffer != NULL);
        if (checkBufferMatchesSlot(*it, buffer)) {
            mSlots[*it].mBufferState = BufferSlot::FREE;
            mQueue.erase(it);
            buffer->setObserver(0);
@@ -756,6 +784,14 @@ void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
    }
}

bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) {
    LOGV("Check if Buffer matches slot");
    // need to convert to char* for pointer arithmetic and then
    // copy the byte stream into our handle
    buffer_handle_t bufferHandle ;
    memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t));
    return mSlots[slot].mGraphicBuffer->handle  ==  bufferHandle;
}


} // end of namespace android
+6 −7
Original line number Diff line number Diff line
@@ -71,8 +71,8 @@ protected:
        mANW.clear();
    }

    const int mYuvTexWidth;//  = 64;
    const int mYuvTexHeight;// = 66;
    const int mYuvTexWidth;
    const int mYuvTexHeight;

    sp<SurfaceMediaSource> mSMS;
    sp<SurfaceTextureClient> mSTC;
@@ -124,7 +124,6 @@ sp<MPEG4Writer> SurfaceMediaSourceTest::setUpWriter(OMXClient &client ) {
    // TODO: overwriting the colorformat since the format set by GRAlloc
    // could be wrong or not be read by OMX
    enc_meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
    // colorFormat);


    sp<MediaSource> encoder =
@@ -225,7 +224,6 @@ TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotOneBufferPass)

    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
            0, 0, HAL_PIXEL_FORMAT_YV12));
                                // OMX_COLOR_FormatYUV420Planar)); // ));
    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));

@@ -239,7 +237,6 @@ TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotWrongSizeBuffe
    // setting the client side buffer size different than the server size
    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
             10, 10, HAL_PIXEL_FORMAT_YV12));
                                // OMX_COLOR_FormatYUV420Planar)); // ));
    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));

@@ -258,6 +255,7 @@ TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPa
            0, 0, HAL_PIXEL_FORMAT_YV12));
    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));

    SimpleDummyRecorder writer(mSMS);
    writer.start();

@@ -276,10 +274,12 @@ TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPa
// A dummy writer is used to simulate actual MPEG4Writer
TEST_F(SurfaceMediaSourceTest,  EncodingFromCpuFilledYV12BufferNpotMultiBufferPassLag) {
    LOGV("Testing MultiBufferPass, Dummy Recorder Lagging **************");

    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
            0, 0, HAL_PIXEL_FORMAT_YV12));
    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));

    SimpleDummyRecorder writer(mSMS);
    writer.start();

@@ -322,10 +322,9 @@ TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPas
TEST_F(SurfaceMediaSourceTest, DISABLED_EncodingFromCpuFilledYV12BufferNpotWrite) {
    LOGV("Testing the whole pipeline with actual Recorder");
    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
            0, 0, HAL_PIXEL_FORMAT_YV12)); // OMX_COLOR_FormatYUV420Planar)); // ));
            0, 0, HAL_PIXEL_FORMAT_YV12));
    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));

    OMXClient client;
    CHECK_EQ(OK, client.connect());