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

Commit 409f95ff authored by Pannag Sanketi's avatar Pannag Sanketi Committed by Android (Google) Code Review
Browse files

Merge "Testing the GL/ CPU encoding w/ Gralloc buffers"

parents 011833c3 557b7092
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -182,9 +182,9 @@ public:

protected:

    // freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
    // freeAllBuffersLocked frees the resources (both GraphicBuffer and EGLImage) for
    // all slots.
    void freeAllBuffers();
    void freeAllBuffersLocked();
    static bool isExternalFormat(uint32_t format);

private:
@@ -337,8 +337,15 @@ private:
    // Set to a default of 30 fps if not specified by the client side
    int32_t mFrameRate;

    // mStarted is a flag to check if the recording has started
    bool mStarted;
    // mStopped is a flag to check if the recording is going on
    bool mStopped;

    // mNumFramesReceived indicates the number of frames recieved from
    // the client side
    int mNumFramesReceived;
    // mNumFramesEncoded indicates the number of frames passed on to the
    // encoder
    int mNumFramesEncoded;

    // mFrameAvailableCondition condition used to indicate whether there
    // is a frame available for dequeuing
+2 −1
Original line number Diff line number Diff line
@@ -154,7 +154,8 @@ typedef enum OMX_COLOR_FORMATTYPE {
     * Gralloc Buffers.
     * FIXME: In the process of reserving some enum values for
     * Android-specific OMX IL colorformats. Change this enum to
     * an acceptable range once that is done.*/
     * an acceptable range once that is done.
     * */
    OMX_COLOR_FormatAndroidOpaque = 0x7F000001,
    OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100,
    OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00,
+13 −2
Original line number Diff line number Diff line
@@ -838,6 +838,15 @@ static size_t getFrameSize(
        case OMX_COLOR_FormatYUV420Planar:
        case OMX_COLOR_FormatYUV420SemiPlanar:
        case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
        /*
        * FIXME: For the Opaque color format, the frame size does not
        * need to be (w*h*3)/2. It just needs to
        * be larger than certain minimum buffer size. However,
        * currently, this opaque foramt has been tested only on
        * YUV420 formats. If that is changed, then we need to revisit
        * this part in the future
        */
        case OMX_COLOR_FormatAndroidOpaque:
            return (width * height * 3) / 2;

        default:
@@ -887,7 +896,7 @@ status_t OMXCodec::isColorFormatSupported(
        // Make sure that omx component does not overwrite
        // the incremented index (bug 2897413).
        CHECK_EQ(index, portFormat.nIndex);
        if ((portFormat.eColorFormat == colorFormat)) {
        if (portFormat.eColorFormat == colorFormat) {
            LOGV("Found supported color format: %d", portFormat.eColorFormat);
            return OK;  // colorFormat is supported!
        }
@@ -2923,6 +2932,7 @@ bool OMXCodec::drainInputBuffer(BufferInfo *info) {
    size_t offset = 0;
    int32_t n = 0;


    for (;;) {
        MediaBuffer *srcBuffer;
        if (mSeekTimeUs >= 0) {
@@ -3021,6 +3031,7 @@ bool OMXCodec::drainInputBuffer(BufferInfo *info) {
                CHECK(info->mMediaBuffer == NULL);
                info->mMediaBuffer = srcBuffer;
            } else {
                CHECK(srcBuffer->data() != NULL) ;
                memcpy((uint8_t *)info->mData + offset,
                        (const uint8_t *)srcBuffer->data()
                            + srcBuffer->range_offset(),
+111 −67
Original line number Diff line number Diff line
@@ -13,7 +13,6 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// #define LOG_NDEBUG 0
#define LOG_TAG "SurfaceMediaSource"

@@ -47,7 +46,9 @@ SurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) :
                mSynchronousMode(true),
                mConnectedApi(NO_CONNECTED_API),
                mFrameRate(30),
                mStarted(false)   {
                mNumFramesReceived(0),
                mNumFramesEncoded(0),
                mStopped(false) {
    LOGV("SurfaceMediaSource::SurfaceMediaSource");
    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
    mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
@@ -55,10 +56,9 @@ SurfaceMediaSource::SurfaceMediaSource(uint32_t bufW, uint32_t bufH) :

SurfaceMediaSource::~SurfaceMediaSource() {
    LOGV("SurfaceMediaSource::~SurfaceMediaSource");
    if (mStarted) {
    if (!mStopped) {
        stop();
    }
    freeAllBuffers();
}

size_t SurfaceMediaSource::getQueuedCount() const {
@@ -139,12 +139,12 @@ status_t SurfaceMediaSource::setBufferCount(int bufferCount) {

    // here we're guaranteed that the client doesn't have dequeued buffers
    // and will release all of its buffer references.
    freeAllBuffers();
    mBufferCount = bufferCount;
    mClientBufferCount = bufferCount;
    mCurrentSlot = INVALID_BUFFER_SLOT;
    mQueue.clear();
    mDequeueCondition.signal();
    freeAllBuffersLocked();
    return OK;
}

@@ -164,7 +164,7 @@ status_t SurfaceMediaSource::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
                                            uint32_t format, uint32_t usage) {
    LOGV("dequeueBuffer");

    Mutex::Autolock lock(mMutex);

    // Check for the buffer size- the client should just use the
    // default width and height, and not try to set those.
@@ -184,10 +184,7 @@ status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
        return BAD_VALUE;
    }

    Mutex::Autolock lock(mMutex);

    status_t returnFlags(OK);

    int found, foundSync;
    int dequeuedCount = 0;
    bool tryAgain = true;
@@ -218,6 +215,9 @@ status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
                LOGV("Waiting for the FIFO to drain");
                mDequeueCondition.wait(mMutex);
            }
            if (mStopped) {
                return NO_INIT;
            }
            // need to check again since the mode could have changed
            // while we were waiting
            minBufferCountNeeded = mSynchronousMode ?
@@ -228,7 +228,7 @@ status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
                ((mServerBufferCount != mBufferCount) ||
                        (mServerBufferCount < minBufferCountNeeded))) {
            // here we're guaranteed that mQueue is empty
            freeAllBuffers();
            freeAllBuffersLocked();
            mBufferCount = mServerBufferCount;
            if (mBufferCount < minBufferCountNeeded)
                mBufferCount = minBufferCountNeeded;
@@ -290,9 +290,12 @@ status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
        // for for some buffers to be consumed
        tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
        if (tryAgain) {
            LOGW("Waiting..In synchronous mode and no buffer to dQ");
            LOGV("Waiting..In synchronous mode and no buffer to dequeue");
            mDequeueCondition.wait(mMutex);
        }
        if (mStopped) {
            return NO_INIT;
        }
    }

    if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
@@ -304,7 +307,7 @@ status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
        return -EBUSY;
    }

    const int buf = found;
    const int bufIndex = found;
    *outBuf = found;

    const bool useDefaultSize = !w && !h;
@@ -322,9 +325,9 @@ status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,

    // buffer is now in DEQUEUED (but can also be current at the same time,
    // if we're in synchronous mode)
    mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
    mSlots[bufIndex].mBufferState = BufferSlot::DEQUEUED;

    const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
    const sp<GraphicBuffer>& buffer(mSlots[bufIndex].mGraphicBuffer);
    if ((buffer == NULL) ||
        (uint32_t(buffer->width)  != w) ||
        (uint32_t(buffer->height) != h) ||
@@ -342,22 +345,25 @@ status_t SurfaceMediaSource::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
            if (updateFormat) {
                mPixelFormat = format;
            }
            mSlots[buf].mGraphicBuffer = graphicBuffer;
            mSlots[buf].mRequestBufferCalled = false;
            mSlots[bufIndex].mGraphicBuffer = graphicBuffer;
            mSlots[bufIndex].mRequestBufferCalled = false;
            returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
    }
    return returnFlags;
}

// TODO: clean this up
status_t SurfaceMediaSource::setSynchronousMode(bool enabled) {
    Mutex::Autolock lock(mMutex);
    if (mStopped) {
        LOGE("setSynchronousMode: SurfaceMediaSource has been stopped!");
        return NO_INIT;
    }

    status_t err = OK;
    if (!enabled) {
        // going to asynchronous mode, drain the queue
        while (mSynchronousMode != enabled && !mQueue.isEmpty()) {
            mDequeueCondition.wait(mMutex);
        }
        // Async mode is not allowed
        LOGE("SurfaceMediaSource can be used only synchronous mode!");
        return INVALID_OPERATION;
    }

    if (mSynchronousMode != enabled) {
@@ -368,13 +374,19 @@ status_t SurfaceMediaSource::setSynchronousMode(bool enabled) {
        mSynchronousMode = enabled;
        mDequeueCondition.signal();
    }
    return err;
    return OK;
}

status_t SurfaceMediaSource::connect(int api,
        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
    LOGV("SurfaceMediaSource::connect");
    Mutex::Autolock lock(mMutex);

    if (mStopped) {
        LOGE("Connect: SurfaceMediaSource has been stopped!");
        return NO_INIT;
    }

    status_t err = NO_ERROR;
    switch (api) {
        case NATIVE_WINDOW_API_EGL:
@@ -397,9 +409,25 @@ status_t SurfaceMediaSource::connect(int api,
    return err;
}

// This is called by the client side when it is done
// TODO: Currently, this also sets mStopped to true which
// is needed for unblocking the encoder which might be
// waiting to read more frames. So if on the client side,
// the same thread supplies the frames and also calls stop
// on the encoder, the client has to call disconnect before
// it calls stop.
// In the case of the camera,
// that need not be required since the thread supplying the
// frames is separate than the one calling stop.
status_t SurfaceMediaSource::disconnect(int api) {
    LOGV("SurfaceMediaSource::disconnect");
    Mutex::Autolock lock(mMutex);

    if (mStopped) {
        LOGE("disconnect: SurfaceMediaSoource is already stopped!");
        return NO_INIT;
    }

    status_t err = NO_ERROR;
    switch (api) {
        case NATIVE_WINDOW_API_EGL:
@@ -408,6 +436,9 @@ status_t SurfaceMediaSource::disconnect(int api) {
        case NATIVE_WINDOW_API_CAMERA:
            if (mConnectedApi == api) {
                mConnectedApi = NO_CONNECTED_API;
                mStopped = true;
                mDequeueCondition.signal();
                mFrameAvailableCondition.signal();
            } else {
                err = -EINVAL;
            }
@@ -419,45 +450,47 @@ status_t SurfaceMediaSource::disconnect(int api) {
    return err;
}

status_t SurfaceMediaSource::queueBuffer(int buf, int64_t timestamp,
status_t SurfaceMediaSource::queueBuffer(int bufIndex, int64_t timestamp,
        uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
    LOGV("queueBuffer");

    Mutex::Autolock lock(mMutex);
    if (buf < 0 || buf >= mBufferCount) {
    if (bufIndex < 0 || bufIndex >= mBufferCount) {
        LOGE("queueBuffer: slot index out of range [0, %d]: %d",
                mBufferCount, buf);
                mBufferCount, bufIndex);
        return -EINVAL;
    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
    } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) {
        LOGE("queueBuffer: slot %d is not owned by the client (state=%d)",
                buf, mSlots[buf].mBufferState);
                bufIndex, mSlots[bufIndex].mBufferState);
        return -EINVAL;
    } else if (!mSlots[buf].mRequestBufferCalled) {
    } else if (!mSlots[bufIndex].mRequestBufferCalled) {
        LOGE("queueBuffer: slot %d was enqueued without requesting a "
                "buffer", buf);
                "buffer", bufIndex);
        return -EINVAL;
    }

    if (mSynchronousMode) {
        // in synchronous mode we queue all buffers in a FIFO
        mQueue.push_back(buf);
        LOGV("Client queued buffer on slot: %d, Q size = %d",
                                                buf, mQueue.size());
        mQueue.push_back(bufIndex);
        mNumFramesReceived++;
        LOGV("Client queued buf# %d @slot: %d, Q size = %d, handle = %p, timestamp = %lld",
            mNumFramesReceived, bufIndex, mQueue.size(),
            mSlots[bufIndex].mGraphicBuffer->handle, timestamp);
    } else {
        // in asynchronous mode we only keep the most recent buffer
        if (mQueue.empty()) {
            mQueue.push_back(buf);
            mQueue.push_back(bufIndex);
        } else {
            Fifo::iterator front(mQueue.begin());
            // buffer currently queued is freed
            mSlots[*front].mBufferState = BufferSlot::FREE;
            // and we record the new buffer index in the queued list
            *front = buf;
            *front = bufIndex;
        }
    }

    mSlots[buf].mBufferState = BufferSlot::QUEUED;
    mSlots[buf].mTimestamp = timestamp;
    mSlots[bufIndex].mBufferState = BufferSlot::QUEUED;
    mSlots[bufIndex].mTimestamp = timestamp;
    // TODO: (Confirm) Don't want to signal dequeue here.
    // May be just in asynchronous mode?
    // mDequeueCondition.signal();
@@ -482,7 +515,7 @@ status_t SurfaceMediaSource::queueBuffer(int buf, int64_t timestamp,
// wait to hear from StageFrightRecorder to set the buffer FREE
// Make sure this is called when the mutex is locked
status_t SurfaceMediaSource::onFrameReceivedLocked() {
    LOGV("On Frame Received");
    LOGV("On Frame Received locked");
    // Signal the encoder that a new frame has arrived
    mFrameAvailableCondition.signal();

@@ -501,19 +534,19 @@ status_t SurfaceMediaSource::onFrameReceivedLocked() {
}


void SurfaceMediaSource::cancelBuffer(int buf) {
void SurfaceMediaSource::cancelBuffer(int bufIndex) {
    LOGV("SurfaceMediaSource::cancelBuffer");
    Mutex::Autolock lock(mMutex);
    if (buf < 0 || buf >= mBufferCount) {
    if (bufIndex < 0 || bufIndex >= mBufferCount) {
        LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
                mBufferCount, buf);
                mBufferCount, bufIndex);
        return;
    } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
    } else if (mSlots[bufIndex].mBufferState != BufferSlot::DEQUEUED) {
        LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
                buf, mSlots[buf].mBufferState);
                bufIndex, mSlots[bufIndex].mBufferState);
        return;
    }
    mSlots[buf].mBufferState = BufferSlot::FREE;
    mSlots[bufIndex].mBufferState = BufferSlot::FREE;
    mDequeueCondition.signal();
}

@@ -531,8 +564,8 @@ void SurfaceMediaSource::setFrameAvailableListener(
    mFrameAvailableListener = listener;
}

void SurfaceMediaSource::freeAllBuffers() {
    LOGV("freeAllBuffers");
void SurfaceMediaSource::freeAllBuffersLocked() {
    LOGV("freeAllBuffersLocked");
    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
        mSlots[i].mGraphicBuffer = 0;
        mSlots[i].mBufferState = BufferSlot::FREE;
@@ -648,10 +681,7 @@ int32_t SurfaceMediaSource::getFrameRate( ) const {

status_t SurfaceMediaSource::start(MetaData *params)
{
    LOGV("start");
    Mutex::Autolock lock(mMutex);
    CHECK(!mStarted);
    mStarted = true;
    LOGV("started!");
    return OK;
}

@@ -662,8 +692,11 @@ status_t SurfaceMediaSource::stop()

    Mutex::Autolock lock(mMutex);
    // TODO: Add waiting on mFrameCompletedCondition here?
    mStarted = false;
    mStopped = true;
    mFrameAvailableCondition.signal();
    mDequeueCondition.signal();
    mQueue.clear();
    freeAllBuffersLocked();

    return OK;
}
@@ -690,21 +723,23 @@ sp<MetaData> SurfaceMediaSource::getFormat()
status_t SurfaceMediaSource::read( MediaBuffer **buffer,
                                    const ReadOptions *options)
{
    Mutex::Autolock autoLock(mMutex) ;

    LOGV("Read. Size of queued buffer: %d", mQueue.size());
    *buffer = NULL;

    Mutex::Autolock autoLock(mMutex) ;
    // If the recording has started and the queue is empty, then just
    // wait here till the frames come in from the client side
    while (mStarted && mQueue.empty()) {
    while (!mStopped && mQueue.empty()) {
        LOGV("NO FRAMES! Recorder waiting for FrameAvailableCondition");
        mFrameAvailableCondition.wait(mMutex);
    }

    // If the loop was exited as a result of stopping the recording,
    // it is OK
    if (!mStarted) {
        return OK;
    if (mStopped) {
        LOGV("Read: SurfaceMediaSource is stopped. Returning NO_INIT;");
        return NO_INIT;
    }

    // Update the current buffer info
@@ -712,15 +747,20 @@ status_t SurfaceMediaSource::read( MediaBuffer **buffer,
    // can be more than one "current" slots.
    Fifo::iterator front(mQueue.begin());
    mCurrentSlot = *front;
    mQueue.erase(front);
    mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer;
    int64_t prevTimeStamp = mCurrentTimestamp;
    mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp;

    mNumFramesEncoded++;
    // 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);
    (*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp / 1000);
    LOGV("Frames encoded = %d, timestamp = %lld, time diff = %lld",
            mNumFramesEncoded, mCurrentTimestamp / 1000,
            mCurrentTimestamp / 1000 - prevTimeStamp / 1000);

    return OK;
}
@@ -743,15 +783,17 @@ void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) {
        new MediaBuffer(4 + sizeof(buffer_handle_t));
    char *data = (char *)tempBuffer->data();
    if (data == NULL) {
        LOGE("Cannot allocate memory for passing buffer metadata!");
        LOGE("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;
}

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

void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
    LOGV("signalBufferReturned");
@@ -759,16 +801,19 @@ void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
    bool foundBuffer = false;
    Mutex::Autolock autoLock(mMutex);

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

    for (Fifo::iterator it = mQueue.begin(); it != mQueue.end(); ++it) {
        CHECK(mSlots[*it].mGraphicBuffer != NULL);
        if (checkBufferMatchesSlot(*it, buffer)) {
            mSlots[*it].mBufferState = BufferSlot::FREE;
            mQueue.erase(it);
    for (int id = 0; id < NUM_BUFFER_SLOTS; id++) {
        if (mSlots[id].mGraphicBuffer == NULL) {
            continue;
        }
        if (checkBufferMatchesSlot(id, buffer)) {
            LOGV("Slot %d returned, matches handle = %p", id,
                    mSlots[id].mGraphicBuffer->handle);
            mSlots[id].mBufferState = BufferSlot::FREE;
            buffer->setObserver(0);
            buffer->release();
            mDequeueCondition.signal();
@@ -792,5 +837,4 @@ bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) {
    return mSlots[slot].mGraphicBuffer->handle  ==  bufferHandle;
}


} // end of namespace android
+4 −3
Original line number Diff line number Diff line
@@ -19,12 +19,13 @@ LOCAL_SHARED_LIBRARIES := \
	libbinder \
	libcutils \
	libgui \
	libstlport \
	libui \
	libutils \
	libmedia \
	libstagefright \
	libstagefright_omx \
	libstagefright_foundation \
	libstlport \
	libui \
	libutils \

LOCAL_STATIC_LIBRARIES := \
	libgtest \
Loading