Merge "Add decode-to-ANativeWindow support to Stagefright."
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,16 +834,25 @@ void AwesomePlayer::initRenderer_l() {
|
||||
IPCThreadState::self()->flushCommands();
|
||||
|
||||
if (mSurface != NULL) {
|
||||
// Other decoders are instantiated locally and as a consequence
|
||||
// allocate their buffers in local address space.
|
||||
mVideoRenderer = new AwesomeLocalRenderer(
|
||||
false, // previewOnly
|
||||
component,
|
||||
(OMX_COLOR_FORMATTYPE)format,
|
||||
mISurface,
|
||||
mSurface,
|
||||
mVideoWidth, mVideoHeight,
|
||||
decodedWidth, decodedHeight);
|
||||
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. This renderer
|
||||
// then performs a color conversion and copy to get the data
|
||||
// into the ANativeBuffer.
|
||||
mVideoRenderer = new AwesomeLocalRenderer(
|
||||
false, // previewOnly
|
||||
component,
|
||||
(OMX_COLOR_FORMATTYPE)format,
|
||||
mISurface,
|
||||
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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <binder/MemoryDealer.h>
|
||||
#include <binder/ProcessState.h>
|
||||
#include <media/IMediaPlayerService.h>
|
||||
#include <media/stagefright/HardwareAPI.h>
|
||||
#include <media/stagefright/MediaBuffer.h>
|
||||
#include <media/stagefright/MediaBufferGroup.h>
|
||||
#include <media/stagefright/MediaDebug.h>
|
||||
@@ -478,7 +479,8 @@ sp<MediaSource> OMXCodec::Create(
|
||||
const sp<MetaData> &meta, bool createEncoder,
|
||||
const sp<MediaSource> &source,
|
||||
const char *matchComponentName,
|
||||
uint32_t flags) {
|
||||
uint32_t flags,
|
||||
const sp<ANativeWindow> &nativeWindow) {
|
||||
const char *mime;
|
||||
bool success = meta->findCString(kKeyMIMEType, &mime);
|
||||
CHECK(success);
|
||||
@@ -534,7 +536,7 @@ sp<MediaSource> OMXCodec::Create(
|
||||
sp<OMXCodec> codec = new OMXCodec(
|
||||
omx, node, quirks,
|
||||
createEncoder, mime, componentName,
|
||||
source);
|
||||
source, nativeWindow);
|
||||
|
||||
observer->setCodec(codec);
|
||||
|
||||
@@ -742,6 +744,15 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta, uint32_t flags) {
|
||||
mQuirks &= ~kOutputBuffersAreUnreadable;
|
||||
}
|
||||
|
||||
if (!mIsEncoder
|
||||
&& !strncasecmp(mMIME, "video/", 6)
|
||||
&& !strncmp(mComponentName, "OMX.", 4)) {
|
||||
status_t err = initNativeWindow();
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -1429,7 +1440,8 @@ OMXCodec::OMXCodec(
|
||||
bool isEncoder,
|
||||
const char *mime,
|
||||
const char *componentName,
|
||||
const sp<MediaSource> &source)
|
||||
const sp<MediaSource> &source,
|
||||
const sp<ANativeWindow> &nativeWindow)
|
||||
: mOMX(omx),
|
||||
mOMXLivesLocally(omx->livesLocally(getpid())),
|
||||
mNode(node),
|
||||
@@ -1449,7 +1461,8 @@ OMXCodec::OMXCodec(
|
||||
mTargetTimeUs(-1),
|
||||
mSkipTimeUs(-1),
|
||||
mLeftOverBuffer(NULL),
|
||||
mPaused(false) {
|
||||
mPaused(false),
|
||||
mNativeWindow(nativeWindow) {
|
||||
mPortStatus[kPortIndexInput] = ENABLED;
|
||||
mPortStatus[kPortIndexOutput] = ENABLED;
|
||||
|
||||
@@ -1593,6 +1606,10 @@ status_t OMXCodec::allocateBuffers() {
|
||||
}
|
||||
|
||||
status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
|
||||
if (mNativeWindow != 0 && portIndex == kPortIndexOutput) {
|
||||
return allocateOutputBuffersFromNativeWindow();
|
||||
}
|
||||
|
||||
OMX_PARAM_PORTDEFINITIONTYPE def;
|
||||
InitOMXParams(&def);
|
||||
def.nPortIndex = portIndex;
|
||||
@@ -1685,6 +1702,178 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
|
||||
// Get the number of buffers needed.
|
||||
OMX_PARAM_PORTDEFINITIONTYPE def;
|
||||
InitOMXParams(&def);
|
||||
def.nPortIndex = kPortIndexOutput;
|
||||
|
||||
status_t err = mOMX->getParameter(
|
||||
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// Check that the color format is in the correct range.
|
||||
CHECK(OMX_COLOR_FormatAndroidPrivateStart <= def.format.video.eColorFormat);
|
||||
CHECK(def.format.video.eColorFormat < OMX_COLOR_FormatAndroidPrivateEnd);
|
||||
|
||||
err = native_window_set_buffers_geometry(
|
||||
mNativeWindow.get(),
|
||||
def.format.video.nFrameWidth,
|
||||
def.format.video.nFrameHeight,
|
||||
def.format.video.eColorFormat
|
||||
- OMX_COLOR_FormatAndroidPrivateStart);
|
||||
|
||||
if (err != 0) {
|
||||
LOGE("native_window_set_buffers_geometry failed: %s (%d)",
|
||||
strerror(-err), -err);
|
||||
return err;
|
||||
}
|
||||
|
||||
// Increase the buffer count by one to allow for the ANativeWindow to hold
|
||||
// on to one of the buffers.
|
||||
def.nBufferCountActual++;
|
||||
err = mOMX->setParameter(
|
||||
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// Set up the native window.
|
||||
// XXX TODO: Get the gralloc usage flags from the OMX plugin!
|
||||
err = native_window_set_usage(
|
||||
mNativeWindow.get(), GRALLOC_USAGE_HW_TEXTURE);
|
||||
if (err != 0) {
|
||||
LOGE("native_window_set_usage failed: %s (%d)", strerror(-err), -err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = native_window_set_buffer_count(
|
||||
mNativeWindow.get(), def.nBufferCountActual);
|
||||
if (err != 0) {
|
||||
LOGE("native_window_set_buffer_count failed: %s (%d)", strerror(-err),
|
||||
-err);
|
||||
return err;
|
||||
}
|
||||
|
||||
// XXX TODO: Do something so the ANativeWindow knows that we'll need to get
|
||||
// the same set of buffers.
|
||||
|
||||
CODEC_LOGI("allocating %lu buffers from a native window of size %lu on "
|
||||
"output port", def.nBufferCountActual, def.nBufferSize);
|
||||
|
||||
// Dequeue buffers and send them to OMX
|
||||
OMX_U32 i;
|
||||
for (i = 0; i < def.nBufferCountActual; i++) {
|
||||
android_native_buffer_t* buf;
|
||||
err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
|
||||
if (err != 0) {
|
||||
LOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
|
||||
break;
|
||||
}
|
||||
|
||||
sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(buf, false));
|
||||
IOMX::buffer_id bufferId;
|
||||
err = mOMX->useGraphicBuffer(mNode, kPortIndexOutput, graphicBuffer,
|
||||
&bufferId);
|
||||
if (err != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
CODEC_LOGV("registered graphic buffer with ID %p (pointer = %p)",
|
||||
bufferId, graphicBuffer.get());
|
||||
|
||||
BufferInfo info;
|
||||
info.mData = NULL;
|
||||
info.mSize = def.nBufferSize;
|
||||
info.mBuffer = bufferId;
|
||||
info.mOwnedByComponent = false;
|
||||
info.mOwnedByNativeWindow = false;
|
||||
info.mMem = NULL;
|
||||
info.mMediaBuffer = new MediaBuffer(graphicBuffer);
|
||||
info.mMediaBuffer->setObserver(this);
|
||||
|
||||
mPortBuffers[kPortIndexOutput].push(info);
|
||||
}
|
||||
|
||||
OMX_U32 cancelStart;
|
||||
OMX_U32 cancelEnd;
|
||||
|
||||
if (err != 0) {
|
||||
// If an error occurred while dequeuing we need to cancel any buffers
|
||||
// that were dequeued.
|
||||
cancelStart = 0;
|
||||
cancelEnd = i;
|
||||
} else {
|
||||
// Return the last two buffers to the native window.
|
||||
// XXX TODO: The number of buffers the native window owns should probably be
|
||||
// queried from it when we put the native window in fixed buffer pool mode
|
||||
// (which needs to be implemented). Currently it's hard-coded to 2.
|
||||
cancelStart = def.nBufferCountActual - 2;
|
||||
cancelEnd = def.nBufferCountActual;
|
||||
}
|
||||
|
||||
for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
|
||||
BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(i);
|
||||
cancelBufferToNativeWindow(info);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
status_t OMXCodec::cancelBufferToNativeWindow(BufferInfo *info) {
|
||||
CHECK(!info->mOwnedByNativeWindow);
|
||||
CODEC_LOGV("Calling cancelBuffer on buffer %p", info->mBuffer);
|
||||
int err = mNativeWindow->cancelBuffer(
|
||||
mNativeWindow.get(), info->mMediaBuffer->graphicBuffer().get());
|
||||
if (err != 0) {
|
||||
CODEC_LOGE("cancelBuffer failed w/ error 0x%08x", err);
|
||||
|
||||
setState(ERROR);
|
||||
return err;
|
||||
}
|
||||
info->mOwnedByNativeWindow = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
|
||||
// Dequeue the next buffer from the native window.
|
||||
android_native_buffer_t* buf;
|
||||
int err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
|
||||
if (err != 0) {
|
||||
CODEC_LOGE("dequeueBuffer failed w/ error 0x%08x", err);
|
||||
|
||||
setState(ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Determine which buffer we just dequeued.
|
||||
Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
|
||||
BufferInfo *bufInfo = 0;
|
||||
for (size_t i = 0; i < buffers->size(); i++) {
|
||||
sp<GraphicBuffer> graphicBuffer = buffers->itemAt(i).
|
||||
mMediaBuffer->graphicBuffer();
|
||||
if (graphicBuffer->handle == buf->handle) {
|
||||
bufInfo = &buffers->editItemAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bufInfo == 0) {
|
||||
CODEC_LOGE("dequeued unrecognized buffer: %p", buf);
|
||||
|
||||
setState(ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The native window no longer owns the buffer.
|
||||
CHECK(bufInfo->mOwnedByNativeWindow);
|
||||
bufInfo->mOwnedByNativeWindow = false;
|
||||
|
||||
return bufInfo;
|
||||
}
|
||||
|
||||
void OMXCodec::on_message(const omx_message &msg) {
|
||||
Mutex::Autolock autoLock(mLock);
|
||||
|
||||
@@ -1769,6 +1958,15 @@ void OMXCodec::on_message(const omx_message &msg) {
|
||||
mOMX->freeBuffer(mNode, kPortIndexOutput, buffer);
|
||||
CHECK_EQ(err, OK);
|
||||
|
||||
// Cancel the buffer if it belongs to an ANativeWindow.
|
||||
if (info->mMediaBuffer != NULL) {
|
||||
sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
|
||||
if (!info->mOwnedByNativeWindow && graphicBuffer != 0) {
|
||||
cancelBufferToNativeWindow(info);
|
||||
// Ignore any errors
|
||||
}
|
||||
}
|
||||
|
||||
buffers->removeAt(i);
|
||||
#if 0
|
||||
} else if (mPortStatus[kPortIndexOutput] == ENABLED
|
||||
@@ -1797,8 +1995,10 @@ void OMXCodec::on_message(const omx_message &msg) {
|
||||
}
|
||||
|
||||
MediaBuffer *buffer = info->mMediaBuffer;
|
||||
bool isGraphicBuffer = buffer->graphicBuffer() != NULL;
|
||||
|
||||
if (msg.u.extended_buffer_data.range_offset
|
||||
if (!isGraphicBuffer
|
||||
&& msg.u.extended_buffer_data.range_offset
|
||||
+ msg.u.extended_buffer_data.range_length
|
||||
> buffer->size()) {
|
||||
CODEC_LOGE(
|
||||
@@ -1822,7 +2022,7 @@ void OMXCodec::on_message(const omx_message &msg) {
|
||||
buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
|
||||
}
|
||||
|
||||
if (mQuirks & kOutputBuffersAreUnreadable) {
|
||||
if (isGraphicBuffer || mQuirks & kOutputBuffersAreUnreadable) {
|
||||
buffer->meta_data()->setInt32(kKeyIsUnreadable, true);
|
||||
}
|
||||
|
||||
@@ -2247,6 +2447,15 @@ status_t OMXCodec::freeBuffersOnPort(
|
||||
// Make sure nobody but us owns this buffer at this point.
|
||||
CHECK_EQ(info->mMediaBuffer->refcount(), 0);
|
||||
|
||||
// Cancel the buffer if it belongs to an ANativeWindow.
|
||||
sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
|
||||
if (!info->mOwnedByNativeWindow && graphicBuffer != 0) {
|
||||
status_t err = cancelBufferToNativeWindow(info);
|
||||
if (err != OK) {
|
||||
stickyErr = err;
|
||||
}
|
||||
}
|
||||
|
||||
info->mMediaBuffer->release();
|
||||
}
|
||||
|
||||
@@ -2321,6 +2530,7 @@ void OMXCodec::enablePortAsync(OMX_U32 portIndex) {
|
||||
CHECK_EQ(mPortStatus[portIndex], DISABLED);
|
||||
mPortStatus[portIndex] = ENABLING;
|
||||
|
||||
CODEC_LOGV("sending OMX_CommandPortEnable(%ld)", portIndex);
|
||||
status_t err =
|
||||
mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
|
||||
CHECK_EQ(err, OK);
|
||||
@@ -2346,7 +2556,10 @@ void OMXCodec::fillOutputBuffers() {
|
||||
|
||||
Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
|
||||
for (size_t i = 0; i < buffers->size(); ++i) {
|
||||
fillOutputBuffer(&buffers->editItemAt(i));
|
||||
BufferInfo *info = &buffers->editItemAt(i);
|
||||
if (!info->mOwnedByNativeWindow) {
|
||||
fillOutputBuffer(&buffers->editItemAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2563,7 +2776,23 @@ void OMXCodec::fillOutputBuffer(BufferInfo *info) {
|
||||
return;
|
||||
}
|
||||
|
||||
CODEC_LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
|
||||
sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
|
||||
if (graphicBuffer != 0) {
|
||||
// When using a native buffer we need to lock the buffer before giving
|
||||
// it to OMX.
|
||||
CHECK(!info->mOwnedByNativeWindow);
|
||||
CODEC_LOGV("Calling lockBuffer on %p", info->mBuffer);
|
||||
int err = mNativeWindow->lockBuffer(mNativeWindow.get(),
|
||||
graphicBuffer.get());
|
||||
if (err != 0) {
|
||||
CODEC_LOGE("lockBuffer failed w/ error 0x%08x", err);
|
||||
|
||||
setState(ERROR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CODEC_LOGV("Calling fillBuffer on buffer %p", info->mBuffer);
|
||||
status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
|
||||
|
||||
if (err != OK) {
|
||||
@@ -3146,7 +3375,32 @@ void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
|
||||
|
||||
if (info->mMediaBuffer == buffer) {
|
||||
CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
|
||||
fillOutputBuffer(info);
|
||||
if (buffer->graphicBuffer() == 0) {
|
||||
fillOutputBuffer(info);
|
||||
} else {
|
||||
sp<MetaData> metaData = info->mMediaBuffer->meta_data();
|
||||
int32_t rendered = 0;
|
||||
if (!metaData->findInt32(kKeyRendered, &rendered)) {
|
||||
rendered = 0;
|
||||
}
|
||||
if (!rendered) {
|
||||
status_t err = cancelBufferToNativeWindow(info);
|
||||
if (err < 0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
info->mOwnedByNativeWindow = true;
|
||||
}
|
||||
|
||||
// Dequeue the next buffer from the native window.
|
||||
BufferInfo *nextBufInfo = dequeueBufferFromNativeWindow();
|
||||
if (nextBufInfo == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Give the buffer to the OMX node to fill.
|
||||
fillOutputBuffer(nextBufInfo);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3479,6 +3733,18 @@ void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
status_t OMXCodec::initNativeWindow() {
|
||||
// Enable use of a GraphicBuffer as the output for this node. This must
|
||||
// happen before getting the IndexParamPortDefinition parameter because it
|
||||
// will affect the pixel format that the node reports.
|
||||
status_t err = mOMX->enableGraphicBuffers(mNode, kPortIndexOutput, OMX_TRUE);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
|
||||
mOutputFormat = new MetaData;
|
||||
mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
|
||||
|
||||
Reference in New Issue
Block a user