Merge "Better buffer status management and verification in OMXCodec."
This commit is contained in:
committed by
Android (Google) Code Review
commit
f69583cde5
@@ -121,10 +121,16 @@ private:
|
||||
kOutputBuffersAreUnreadable = 8192,
|
||||
};
|
||||
|
||||
enum BufferStatus {
|
||||
OWNED_BY_US,
|
||||
OWNED_BY_COMPONENT,
|
||||
OWNED_BY_NATIVE_WINDOW,
|
||||
OWNED_BY_CLIENT,
|
||||
};
|
||||
|
||||
struct BufferInfo {
|
||||
IOMX::buffer_id mBuffer;
|
||||
bool mOwnedByComponent;
|
||||
bool mOwnedByNativeWindow;
|
||||
BufferStatus mStatus;
|
||||
sp<IMemory> mMem;
|
||||
size_t mSize;
|
||||
void *mData;
|
||||
@@ -248,9 +254,9 @@ private:
|
||||
|
||||
status_t freeBuffer(OMX_U32 portIndex, size_t bufIndex);
|
||||
|
||||
void drainInputBuffer(IOMX::buffer_id buffer);
|
||||
bool drainInputBuffer(IOMX::buffer_id buffer);
|
||||
void fillOutputBuffer(IOMX::buffer_id buffer);
|
||||
void drainInputBuffer(BufferInfo *info);
|
||||
bool drainInputBuffer(BufferInfo *info);
|
||||
void fillOutputBuffer(BufferInfo *info);
|
||||
|
||||
void drainInputBuffers();
|
||||
|
||||
@@ -1650,8 +1650,7 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
|
||||
}
|
||||
|
||||
info.mBuffer = buffer;
|
||||
info.mOwnedByComponent = false;
|
||||
info.mOwnedByNativeWindow = false;
|
||||
info.mStatus = OWNED_BY_US;
|
||||
info.mMem = mem;
|
||||
info.mMediaBuffer = NULL;
|
||||
|
||||
@@ -1759,8 +1758,7 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
|
||||
info.mData = NULL;
|
||||
info.mSize = def.nBufferSize;
|
||||
info.mBuffer = bufferId;
|
||||
info.mOwnedByComponent = false;
|
||||
info.mOwnedByNativeWindow = false;
|
||||
info.mStatus = OWNED_BY_US;
|
||||
info.mMem = NULL;
|
||||
info.mMediaBuffer = new MediaBuffer(graphicBuffer);
|
||||
info.mMediaBuffer->setObserver(this);
|
||||
@@ -1794,7 +1792,7 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
|
||||
}
|
||||
|
||||
status_t OMXCodec::cancelBufferToNativeWindow(BufferInfo *info) {
|
||||
CHECK(!info->mOwnedByNativeWindow);
|
||||
CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
|
||||
CODEC_LOGV("Calling cancelBuffer on buffer %p", info->mBuffer);
|
||||
int err = mNativeWindow->cancelBuffer(
|
||||
mNativeWindow.get(), info->mMediaBuffer->graphicBuffer().get());
|
||||
@@ -1804,7 +1802,7 @@ status_t OMXCodec::cancelBufferToNativeWindow(BufferInfo *info) {
|
||||
setState(ERROR);
|
||||
return err;
|
||||
}
|
||||
info->mOwnedByNativeWindow = true;
|
||||
info->mStatus = OWNED_BY_NATIVE_WINDOW;
|
||||
return OK;
|
||||
}
|
||||
|
||||
@@ -1839,8 +1837,8 @@ OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
|
||||
}
|
||||
|
||||
// The native window no longer owns the buffer.
|
||||
CHECK(bufInfo->mOwnedByNativeWindow);
|
||||
bufInfo->mOwnedByNativeWindow = false;
|
||||
CHECK_EQ((int)bufInfo->mStatus, (int)OWNED_BY_NATIVE_WINDOW);
|
||||
bufInfo->mStatus = OWNED_BY_US;
|
||||
|
||||
return bufInfo;
|
||||
}
|
||||
@@ -1871,13 +1869,13 @@ void OMXCodec::on_message(const omx_message &msg) {
|
||||
}
|
||||
|
||||
CHECK(i < buffers->size());
|
||||
if (!(*buffers)[i].mOwnedByComponent) {
|
||||
if ((*buffers)[i].mStatus != OWNED_BY_COMPONENT) {
|
||||
LOGW("We already own input buffer %p, yet received "
|
||||
"an EMPTY_BUFFER_DONE.", buffer);
|
||||
}
|
||||
|
||||
BufferInfo* info = &buffers->editItemAt(i);
|
||||
info->mOwnedByComponent = false;
|
||||
info->mStatus = OWNED_BY_US;
|
||||
|
||||
// Buffer could not be released until empty buffer done is called.
|
||||
if (info->mMediaBuffer != NULL) {
|
||||
@@ -1926,12 +1924,12 @@ void OMXCodec::on_message(const omx_message &msg) {
|
||||
CHECK(i < buffers->size());
|
||||
BufferInfo *info = &buffers->editItemAt(i);
|
||||
|
||||
if (!info->mOwnedByComponent) {
|
||||
if (info->mStatus != OWNED_BY_COMPONENT) {
|
||||
LOGW("We already own output buffer %p, yet received "
|
||||
"a FILL_BUFFER_DONE.", buffer);
|
||||
}
|
||||
|
||||
info->mOwnedByComponent = false;
|
||||
info->mStatus = OWNED_BY_US;
|
||||
|
||||
if (mPortStatus[kPortIndexOutput] == DISABLING) {
|
||||
CODEC_LOGV("Port is disabled, freeing buffer %p", buffer);
|
||||
@@ -2400,7 +2398,7 @@ void OMXCodec::onStateChange(OMX_STATETYPE newState) {
|
||||
size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
|
||||
size_t n = 0;
|
||||
for (size_t i = 0; i < buffers.size(); ++i) {
|
||||
if (!buffers[i].mOwnedByComponent) {
|
||||
if (buffers[i].mStatus != OWNED_BY_COMPONENT) {
|
||||
++n;
|
||||
}
|
||||
}
|
||||
@@ -2417,11 +2415,12 @@ status_t OMXCodec::freeBuffersOnPort(
|
||||
for (size_t i = buffers->size(); i-- > 0;) {
|
||||
BufferInfo *info = &buffers->editItemAt(i);
|
||||
|
||||
if (onlyThoseWeOwn && info->mOwnedByComponent) {
|
||||
if (onlyThoseWeOwn && info->mStatus == OWNED_BY_COMPONENT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CHECK_EQ((int)info->mOwnedByComponent, (int)false);
|
||||
CHECK(info->mStatus == OWNED_BY_US
|
||||
|| info->mStatus == OWNED_BY_NATIVE_WINDOW);
|
||||
|
||||
CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
|
||||
|
||||
@@ -2454,7 +2453,7 @@ status_t OMXCodec::freeBuffer(OMX_U32 portIndex, size_t bufIndex) {
|
||||
|
||||
// Cancel the buffer if it belongs to an ANativeWindow.
|
||||
sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
|
||||
if (!info->mOwnedByNativeWindow && graphicBuffer != 0) {
|
||||
if (info->mStatus == OWNED_BY_US && graphicBuffer != 0) {
|
||||
err = cancelBufferToNativeWindow(info);
|
||||
}
|
||||
|
||||
@@ -2559,7 +2558,7 @@ void OMXCodec::fillOutputBuffers() {
|
||||
Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
|
||||
for (size_t i = 0; i < buffers->size(); ++i) {
|
||||
BufferInfo *info = &buffers->editItemAt(i);
|
||||
if (!info->mOwnedByNativeWindow) {
|
||||
if (info->mStatus == OWNED_BY_US) {
|
||||
fillOutputBuffer(&buffers->editItemAt(i));
|
||||
}
|
||||
}
|
||||
@@ -2570,15 +2569,17 @@ void OMXCodec::drainInputBuffers() {
|
||||
|
||||
Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
|
||||
for (size_t i = 0; i < buffers->size(); ++i) {
|
||||
drainInputBuffer(&buffers->editItemAt(i));
|
||||
if (!drainInputBuffer(&buffers->editItemAt(i))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OMXCodec::drainInputBuffer(BufferInfo *info) {
|
||||
CHECK_EQ((int)info->mOwnedByComponent, (int)false);
|
||||
bool OMXCodec::drainInputBuffer(BufferInfo *info) {
|
||||
CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
|
||||
|
||||
if (mSignalledEOS) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
|
||||
@@ -2614,14 +2615,14 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) {
|
||||
0);
|
||||
CHECK_EQ(err, (status_t)OK);
|
||||
|
||||
info->mOwnedByComponent = true;
|
||||
info->mStatus = OWNED_BY_COMPONENT;
|
||||
|
||||
++mCodecSpecificDataIndex;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mPaused) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
status_t err;
|
||||
@@ -2631,6 +2632,7 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) {
|
||||
|
||||
size_t offset = 0;
|
||||
int32_t n = 0;
|
||||
|
||||
for (;;) {
|
||||
MediaBuffer *srcBuffer;
|
||||
MediaSource::ReadOptions options;
|
||||
@@ -2689,7 +2691,7 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) {
|
||||
srcBuffer = NULL;
|
||||
|
||||
setState(ERROR);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
mLeftOverBuffer = srcBuffer;
|
||||
@@ -2699,9 +2701,15 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) {
|
||||
bool releaseBuffer = true;
|
||||
if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
|
||||
CHECK(mOMXLivesLocally && offset == 0);
|
||||
OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *) info->mBuffer;
|
||||
|
||||
OMX_BUFFERHEADERTYPE *header =
|
||||
(OMX_BUFFERHEADERTYPE *)info->mBuffer;
|
||||
|
||||
CHECK(header->pBuffer == info->mData);
|
||||
header->pBuffer = (OMX_U8 *) srcBuffer->data() + srcBuffer->range_offset();
|
||||
|
||||
header->pBuffer =
|
||||
(OMX_U8 *)srcBuffer->data() + srcBuffer->range_offset();
|
||||
|
||||
releaseBuffer = false;
|
||||
info->mMediaBuffer = srcBuffer;
|
||||
} else {
|
||||
@@ -2710,7 +2718,8 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) {
|
||||
info->mMediaBuffer = srcBuffer;
|
||||
}
|
||||
memcpy((uint8_t *)info->mData + offset,
|
||||
(const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
|
||||
(const uint8_t *)srcBuffer->data()
|
||||
+ srcBuffer->range_offset(),
|
||||
srcBuffer->range_length());
|
||||
}
|
||||
|
||||
@@ -2766,10 +2775,10 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) {
|
||||
|
||||
if (err != OK) {
|
||||
setState(ERROR);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
info->mOwnedByComponent = true;
|
||||
info->mStatus = OWNED_BY_COMPONENT;
|
||||
|
||||
// This component does not ever signal the EOS flag on output buffers,
|
||||
// Thanks for nothing.
|
||||
@@ -2777,10 +2786,12 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) {
|
||||
mNoMoreOutputData = true;
|
||||
mBufferFilled.signal();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OMXCodec::fillOutputBuffer(BufferInfo *info) {
|
||||
CHECK_EQ((int)info->mOwnedByComponent, (int)false);
|
||||
CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
|
||||
|
||||
if (mNoMoreOutputData) {
|
||||
CODEC_LOGV("There is no more output data available, not "
|
||||
@@ -2793,7 +2804,6 @@ void OMXCodec::fillOutputBuffer(BufferInfo *info) {
|
||||
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());
|
||||
@@ -2816,19 +2826,20 @@ void OMXCodec::fillOutputBuffer(BufferInfo *info) {
|
||||
return;
|
||||
}
|
||||
|
||||
info->mOwnedByComponent = true;
|
||||
info->mStatus = OWNED_BY_COMPONENT;
|
||||
}
|
||||
|
||||
void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
|
||||
bool OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
|
||||
Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
|
||||
for (size_t i = 0; i < buffers->size(); ++i) {
|
||||
if ((*buffers)[i].mBuffer == buffer) {
|
||||
drainInputBuffer(&buffers->editItemAt(i));
|
||||
return;
|
||||
return drainInputBuffer(&buffers->editItemAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
CHECK(!"should not be here.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
|
||||
@@ -3374,6 +3385,9 @@ status_t OMXCodec::read(
|
||||
mFilledBuffers.erase(mFilledBuffers.begin());
|
||||
|
||||
BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
|
||||
CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
|
||||
info->mStatus = OWNED_BY_CLIENT;
|
||||
|
||||
info->mMediaBuffer->add_ref();
|
||||
*buffer = info->mMediaBuffer;
|
||||
|
||||
@@ -3389,6 +3403,10 @@ void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
|
||||
|
||||
if (info->mMediaBuffer == buffer) {
|
||||
CHECK_EQ((int)mPortStatus[kPortIndexOutput], (int)ENABLED);
|
||||
CHECK_EQ((int)info->mStatus, (int)OWNED_BY_CLIENT);
|
||||
|
||||
info->mStatus = OWNED_BY_US;
|
||||
|
||||
if (buffer->graphicBuffer() == 0) {
|
||||
fillOutputBuffer(info);
|
||||
} else {
|
||||
@@ -3402,10 +3420,10 @@ void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
|
||||
if (err < 0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
info->mOwnedByNativeWindow = true;
|
||||
}
|
||||
|
||||
info->mStatus = OWNED_BY_NATIVE_WINDOW;
|
||||
|
||||
// Dequeue the next buffer from the native window.
|
||||
BufferInfo *nextBufInfo = dequeueBufferFromNativeWindow();
|
||||
if (nextBufInfo == 0) {
|
||||
|
||||
Reference in New Issue
Block a user