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

Commit f18da552 authored by Jamie Gennis's avatar Jamie Gennis Committed by Android Git Automerger
Browse files

am 33e28dd3: Merge "SurfaceMediaSource: keep refs to current buffers" into jb-dev

* commit '33e28dd3':
  SurfaceMediaSource: keep refs to current buffers
parents 18faac2a 33e28dd3
Loading
Loading
Loading
Loading
+6 −12
Original line number Diff line number Diff line
@@ -79,10 +79,6 @@ 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;
@@ -105,9 +101,6 @@ public:
    // when a new frame becomes available.
    void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);

    // getCurrentBuffer returns the buffer associated with the current image.
    sp<GraphicBuffer> getCurrentBuffer() const;

    // dump our state in a String
    void dump(String8& result) const;
    void dump(String8& result, const char* prefix, char* buffer,
@@ -165,11 +158,12 @@ private:
    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
    int mCurrentSlot;

    // mCurrentBuf is the graphic buffer of the current slot to be used by
    // buffer consumer. It's possible that this buffer is not associated
    // with any buffer slot, so we must track it separately in order to
    // properly use IGraphicBufferAlloc::freeAllGraphicBuffersExcept.
    sp<GraphicBuffer> mCurrentBuf;
    // mCurrentBuffers is a list of the graphic buffers that are being used by
    // buffer consumer (i.e. the video encoder). It's possible that these
    // buffers are not associated with any buffer slots, so we must track them
    // separately.  Buffers are added to this list in read, and removed from
    // this list in signalBufferReturned
    Vector<sp<GraphicBuffer> > mCurrentBuffers;

    // mCurrentTimestamp is the timestamp for the current texture. It
    // gets set to mLastQueuedTimestamp each time updateTexImage is called.
+52 −48
Original line number Diff line number Diff line
@@ -96,11 +96,6 @@ void SurfaceMediaSource::setFrameAvailableListener(
    mFrameAvailableListener = listener;
}

sp<GraphicBuffer> SurfaceMediaSource::getCurrentBuffer() const {
    Mutex::Autolock lock(mMutex);
    return mCurrentBuf;
}

void SurfaceMediaSource::dump(String8& result) const
{
    char buffer[1024];
@@ -185,6 +180,35 @@ sp<MetaData> SurfaceMediaSource::getFormat()
    return meta;
}

// 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
static void passMetadataBuffer(MediaBuffer **buffer,
        buffer_handle_t bufferHandle) {
    // MediaBuffer allocates and owns this data
    MediaBuffer *tempBuffer = new MediaBuffer(4 + sizeof(buffer_handle_t));
    char *data = (char *)tempBuffer->data();
    if (data == NULL) {
        ALOGE("Cannot allocate memory for metadata buffer!");
        return;
    }
    OMX_U32 type = kMetadataBufferTypeGrallocSource;
    memcpy(data, &type, 4);
    memcpy(data + 4, &bufferHandle, sizeof(buffer_handle_t));
    *buffer = tempBuffer;

    ALOGV("handle = %p, , offset = %d, length = %d",
            bufferHandle, (*buffer)->range_length(), (*buffer)->range_offset());
}

status_t SurfaceMediaSource::read( MediaBuffer **buffer,
                                    const ReadOptions *options)
{
@@ -251,13 +275,14 @@ status_t SurfaceMediaSource::read( MediaBuffer **buffer,
    if (item.mGraphicBuffer != NULL) {
        mBufferSlot[mCurrentSlot] = item.mGraphicBuffer;
    }
    mCurrentBuf = mBufferSlot[mCurrentSlot];

    mCurrentBuffers.push_back(mBufferSlot[mCurrentSlot]);
    int64_t prevTimeStamp = mCurrentTimestamp;
    mCurrentTimestamp = item.mTimestamp;

    mNumFramesEncoded++;
    // Pass the data to the MediaBuffer. Pass in only the metadata
    passMetadataBufferLocked(buffer);
    passMetadataBuffer(buffer, mBufferSlot[mCurrentSlot]->handle);

    (*buffer)->setObserver(this);
    (*buffer)->add_ref();
@@ -270,34 +295,12 @@ 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) {
    ALOGV("passMetadataBuffer");
    // MediaBuffer allocates and owns this data
    MediaBuffer *tempBuffer =
        new MediaBuffer(4 + sizeof(buffer_handle_t));
    char *data = (char *)tempBuffer->data();
    if (data == NULL) {
        ALOGE("Cannot allocate memory for metadata buffer!");
        return;
    }
    OMX_U32 type = kMetadataBufferTypeGrallocSource;
    memcpy(data, &type, 4);
    memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t));
    *buffer = tempBuffer;

    ALOGV("handle = %p, , offset = %d, length = %d",
            mCurrentBuf->handle, (*buffer)->range_length(), (*buffer)->range_offset());
static buffer_handle_t getMediaBufferHandle(MediaBuffer *buffer) {
    // 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 bufferHandle;
}

void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
@@ -307,16 +310,26 @@ void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {

    Mutex::Autolock lock(mMutex);

    if (mStopped) {
        ALOGV("signalBufferReturned: mStopped = true! Nothing to do!");
        return;
    buffer_handle_t bufferHandle = getMediaBufferHandle(buffer);

    for (size_t i = 0; i < mCurrentBuffers.size(); i++) {
        if (mCurrentBuffers[i]->handle == bufferHandle) {
            mCurrentBuffers.removeAt(i);
            foundBuffer = true;
            break;
        }
    }

    if (!foundBuffer) {
        ALOGW("returned buffer was not found in the current buffer list");
    }

    for (int id = 0; id < BufferQueue::NUM_BUFFER_SLOTS; id++) {
        if (mBufferSlot[id] == NULL) {
            continue;
        }
        if (checkBufferMatchesSlot(id, buffer)) {

        if (bufferHandle == mBufferSlot[id]->handle) {
            ALOGV("Slot %d returned, matches handle = %p", id,
                    mBufferSlot[id]->handle);

@@ -335,15 +348,6 @@ void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
    }
}

bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) {
    ALOGV("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 mBufferSlot[slot]->handle  ==  bufferHandle;
}

// Part of the BufferQueue::ConsumerListener
void SurfaceMediaSource::onFrameAvailable() {
    ALOGV("onFrameAvailable");