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

Commit 92f987a0 authored by Jamie Gennis's avatar Jamie Gennis Committed by Android (Google) Code Review
Browse files

Merge "Add decode-to-ANativeWindow support to Stagefright."

parents be003980 58a36ada
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@

namespace android {

class GraphicBuffer;
class MediaBuffer;
class MediaBufferObserver;
class MetaData;
@@ -48,6 +49,8 @@ public:

    MediaBuffer(size_t size);

    MediaBuffer(const sp<GraphicBuffer>& graphicBuffer);

    // Decrements the reference count and returns the buffer to its
    // associated MediaBufferGroup if the reference count drops to 0.
    void release();
@@ -63,6 +66,8 @@ public:

    void set_range(size_t offset, size_t length);

    sp<GraphicBuffer> graphicBuffer() const;

    sp<MetaData> meta_data();

    // Clears meta data and resets the range to the full extent.
@@ -94,6 +99,7 @@ private:

    void *mData;
    size_t mSize, mRangeOffset, mRangeLength;
    sp<GraphicBuffer> mGraphicBuffer;

    bool mOwnsData;

+3 −0
Original line number Diff line number Diff line
@@ -99,6 +99,9 @@ enum {
    kKeyValidSamples      = 'valD',  // int32_t

    kKeyIsUnreadable      = 'unre',  // bool (int32_t)

    // An indication that a video buffer has been rendered.
    kKeyRendered          = 'rend',  // bool (int32_t)
};

enum {
+19 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#define OMX_CODEC_H_

#include <android/native_window.h>
#include <media/IOMX.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaSource.h>
@@ -44,7 +45,8 @@ struct OMXCodec : public MediaSource,
            const sp<MetaData> &meta, bool createEncoder,
            const sp<MediaSource> &source,
            const char *matchComponentName = NULL,
            uint32_t flags = 0);
            uint32_t flags = 0,
            const sp<ANativeWindow> &nativeWindow = NULL);

    static void setComponentRole(
            const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder,
@@ -114,6 +116,7 @@ private:
    struct BufferInfo {
        IOMX::buffer_id mBuffer;
        bool mOwnedByComponent;
        bool mOwnedByNativeWindow;
        sp<IMemory> mMem;
        size_t mSize;
        void *mData;
@@ -159,13 +162,21 @@ private:

    bool mPaused;

    sp<ANativeWindow> mNativeWindow;

    // The index in each of the mPortBuffers arrays of the buffer that will be
    // submitted to OMX next.  This only applies when using buffers from a
    // native window.
    size_t mNextNativeBufferIndex[2];

    // A list of indices into mPortStatus[kPortIndexOutput] filled with data.
    List<size_t> mFilledBuffers;
    Condition mBufferFilled;

    OMXCodec(const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
             bool isEncoder, const char *mime, const char *componentName,
             const sp<MediaSource> &source);
             const sp<MediaSource> &source,
             const sp<ANativeWindow> &nativeWindow);

    void addCodecSpecificData(const void *data, size_t size);
    void clearCodecSpecificData();
@@ -216,6 +227,11 @@ private:

    status_t allocateBuffers();
    status_t allocateBuffersOnPort(OMX_U32 portIndex);
    status_t allocateOutputBuffersFromNativeWindow();

    status_t queueBufferToNativeWindow(BufferInfo *info);
    status_t cancelBufferToNativeWindow(BufferInfo *info);
    BufferInfo* dequeueBufferFromNativeWindow();

    status_t freeBuffersOnPort(
            OMX_U32 portIndex, bool onlyThoseWeOwn = false);
@@ -250,6 +266,7 @@ private:

    status_t init();
    void initOutputFormat(const sp<MetaData> &inputFormat);
    status_t initNativeWindow();

    void dumpPortStatus(OMX_U32 portIndex);

+49 −12
Original line number Diff line number Diff line
@@ -194,6 +194,35 @@ void AwesomeLocalRenderer::init(
    }
}

struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
    AwesomeNativeWindowRenderer(const sp<ANativeWindow> &nativeWindow)
        : mNativeWindow(nativeWindow) {
    }

    virtual void render(MediaBuffer *buffer) {
        status_t err = mNativeWindow->queueBuffer(
                mNativeWindow.get(), buffer->graphicBuffer().get());
        if (err != 0) {
            LOGE("queueBuffer failed with error %s (%d)", strerror(-err),
                    -err);
            return;
        }

        sp<MetaData> metaData = buffer->meta_data();
        metaData->setInt32(kKeyRendered, 1);
    }

protected:
    virtual ~AwesomeNativeWindowRenderer() {}

private:
    sp<ANativeWindow> mNativeWindow;

    AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
    AwesomeNativeWindowRenderer &operator=(
            const AwesomeNativeWindowRenderer &);
};

AwesomePlayer::AwesomePlayer()
    : mQueueStarted(false),
      mTimeSource(NULL),
@@ -805,8 +834,16 @@ void AwesomePlayer::initRenderer_l() {
        IPCThreadState::self()->flushCommands();

        if (mSurface != NULL) {
            if (strncmp(component, "OMX.", 4) == 0) {
                // Hardware decoders avoid the CPU color conversion by decoding
                // directly to ANativeBuffers, so we must use a renderer that
                // just pushes those buffers to the ANativeWindow.
                mVideoRenderer = new AwesomeNativeWindowRenderer(mSurface);
            } else {
                // Other decoders are instantiated locally and as a consequence
            // allocate their buffers in local address space.
                // allocate their buffers in local address space.  This renderer
                // then performs a color conversion and copy to get the data
                // into the ANativeBuffer.
                mVideoRenderer = new AwesomeLocalRenderer(
                    false,  // previewOnly
                    component,
@@ -815,6 +852,7 @@ void AwesomePlayer::initRenderer_l() {
                    mSurface,
                    mVideoWidth, mVideoHeight,
                    decodedWidth, decodedHeight);
            }
        } else {
            // Our OMX codecs allocate buffers on the media_server side
            // therefore they require a remote IOMXRenderer that knows how
@@ -1054,7 +1092,7 @@ status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
            mClient.interface(), mVideoTrack->getFormat(),
            false, // createEncoder
            mVideoTrack,
            NULL, flags);
            NULL, flags, mSurface);

    if (mVideoSource != NULL) {
        int64_t durationUs;
@@ -1811,4 +1849,3 @@ void AwesomePlayer::postAudioSeekComplete() {
}

}  // namespace android
+26 −3
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MetaData.h>

#include <ui/GraphicBuffer.h>

namespace android {

// XXX make this truly atomic.
@@ -61,6 +63,20 @@ MediaBuffer::MediaBuffer(size_t size)
      mOriginal(NULL) {
}

MediaBuffer::MediaBuffer(const sp<GraphicBuffer>& graphicBuffer)
    : mObserver(NULL),
      mNextBuffer(NULL),
      mRefCount(0),
      mData(NULL),
      mSize(1),
      mRangeOffset(0),
      mRangeLength(mSize),
      mGraphicBuffer(graphicBuffer),
      mOwnsData(false),
      mMetaData(new MetaData),
      mOriginal(NULL) {
}

void MediaBuffer::release() {
    if (mObserver == NULL) {
        CHECK_EQ(mRefCount, 0);
@@ -92,10 +108,12 @@ void MediaBuffer::add_ref() {
}

void *MediaBuffer::data() const {
    CHECK(mGraphicBuffer == NULL);
    return mData;
}

size_t MediaBuffer::size() const {
    CHECK(mGraphicBuffer == NULL);
    return mSize;
}

@@ -108,15 +126,19 @@ size_t MediaBuffer::range_length() const {
}

void MediaBuffer::set_range(size_t offset, size_t length) {
    if (offset + length > mSize) {
    if ((mGraphicBuffer == NULL) && (offset + length > mSize)) {
        LOGE("offset = %d, length = %d, mSize = %d", offset, length, mSize);
    }
    CHECK(offset + length <= mSize);
    CHECK((mGraphicBuffer != NULL) || (offset + length <= mSize));

    mRangeOffset = offset;
    mRangeLength = length;
}

sp<GraphicBuffer> MediaBuffer::graphicBuffer() const {
    return mGraphicBuffer;
}

sp<MetaData> MediaBuffer::meta_data() {
    return mMetaData;
}
@@ -158,6 +180,8 @@ int MediaBuffer::refcount() const {
}

MediaBuffer *MediaBuffer::clone() {
    CHECK_EQ(mGraphicBuffer, NULL);

    MediaBuffer *buffer = new MediaBuffer(mData, mSize);
    buffer->set_range(mRangeOffset, mRangeLength);
    buffer->mMetaData = new MetaData(*mMetaData.get());
@@ -169,4 +193,3 @@ MediaBuffer *MediaBuffer::clone() {
}

}  // namespace android
Loading