aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-10-19 23:59:44 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-10-19 23:59:44 +0000
commit32169693ce2bcbbcaf1f7064707789bc6b55c0ac (patch)
treeb207ce2b6cb08f3ba9b14ea81e060885101abb7a
parent785669782cee8bd0f9df314cded506a749cd45c1 (diff)
parentec976846efd4d2d8b1b00652b69e3c2f526980f3 (diff)
downloadv4l2_codec2-android11-mainline-release.tar.gz
Change-Id: Ided92dd099abc819807ff1ba0c02fb116c4e0004
-rw-r--r--components/V4L2Decoder.cpp79
-rw-r--r--components/include/v4l2_codec2/components/V4L2Decoder.h1
-rw-r--r--tests/c2_e2e_test/src/org/chromium/c2/test/E2eTestActivity.java20
3 files changed, 69 insertions, 31 deletions
diff --git a/components/V4L2Decoder.cpp b/components/V4L2Decoder.cpp
index c070d64..d52bd6c 100644
--- a/components/V4L2Decoder.cpp
+++ b/components/V4L2Decoder.cpp
@@ -270,8 +270,9 @@ void V4L2Decoder::pumpDecodeRequest() {
auto request = std::move(mDecodeRequests.front());
mDecodeRequests.pop();
- ALOGV("QBUF to input queue, bitstreadId=%d", request.buffer->id);
- inputBuffer->SetTimeStamp({.tv_sec = request.buffer->id});
+ const int32_t bitstreamId = request.buffer->id;
+ ALOGV("QBUF to input queue, bitstreadId=%d", bitstreamId);
+ inputBuffer->SetTimeStamp({.tv_sec = bitstreamId});
size_t planeSize = inputBuffer->GetPlaneSize(0);
if (request.buffer->size > planeSize) {
ALOGE("The input size (%zu) is not enough, we need %zu", planeSize,
@@ -286,9 +287,13 @@ void V4L2Decoder::pumpDecodeRequest() {
inputBuffer->SetPlaneBytesUsed(0, request.buffer->offset + request.buffer->size);
std::vector<int> fds;
fds.push_back(std::move(request.buffer->dmabuf_fd));
- std::move(*inputBuffer).QueueDMABuf(fds);
+ if (!std::move(*inputBuffer).QueueDMABuf(fds)) {
+ ALOGE("%s(): Failed to QBUF to input queue, bitstreamId=%d", __func__, bitstreamId);
+ onError();
+ return;
+ }
- mPendingDecodeCbs.insert(std::make_pair(request.buffer->id, std::move(request.decodeCb)));
+ mPendingDecodeCbs.insert(std::make_pair(bitstreamId, std::move(request.decodeCb)));
}
}
@@ -387,15 +392,43 @@ void V4L2Decoder::serviceDeviceTask(bool event) {
outputDequeued = true;
+ const size_t bufferId = dequeuedBuffer->BufferId();
+ const int32_t bitstreamId = static_cast<int32_t>(dequeuedBuffer->GetTimeStamp().tv_sec);
+ const size_t bytesUsed = dequeuedBuffer->GetPlaneBytesUsed(0);
+ const bool isLast = dequeuedBuffer->IsLast();
ALOGV("DQBUF from output queue, bufferId=%zu, corresponding bitstreamId=%d, bytesused=%zu",
- dequeuedBuffer->BufferId(),
- static_cast<int32_t>(dequeuedBuffer->GetTimeStamp().tv_sec),
- dequeuedBuffer->GetPlaneBytesUsed(0));
- if (dequeuedBuffer->GetPlaneBytesUsed(0) > 0) {
- sendOutputBuffer(dequeuedBuffer);
+ bufferId, bitstreamId, bytesUsed);
+
+ // Get the corresponding VideoFrame of the dequeued buffer.
+ auto it = mFrameAtDevice.find(bufferId);
+ ALOG_ASSERT(it != mFrameAtDevice.end(), "buffer %zu is not found at mFrameAtDevice",
+ bufferId);
+ auto frame = std::move(it->second);
+ mFrameAtDevice.erase(it);
+
+ if (bytesUsed > 0) {
+ ALOGV("Send output frame(bitstreamId=%d) to client", bitstreamId);
+ frame->setBitstreamId(bitstreamId);
+ frame->setVisibleRect(mVisibleRect);
+ mOutputCb.Run(std::move(frame));
+ } else {
+ // Workaround(b/168750131): If the buffer is not enqueued before the next drain is done,
+ // then the driver will fail to notify EOS. So we recycle the buffer immediately.
+ ALOGV("Recycle empty buffer %zu back to V4L2 output queue.", bufferId);
+ dequeuedBuffer.reset();
+ auto outputBuffer = mOutputQueue->GetFreeBuffer(bufferId);
+ ALOG_ASSERT(outputBuffer, "V4L2 output queue slot %zu is not freed.", bufferId);
+
+ if (!std::move(*outputBuffer).QueueDMABuf(frame->getFDs())) {
+ ALOGE("%s(): Failed to recycle empty buffer to output queue.", __func__);
+ onError();
+ return;
+ }
+ mFrameAtDevice.insert(std::make_pair(bufferId, std::move(frame)));
}
- if (mDrainCb && dequeuedBuffer->IsLast()) {
- ALOGD("All buffers are drained.");
+
+ if (mDrainCb && isLast) {
+ ALOGV("All buffers are drained.");
sendV4L2DecoderCmd(true);
std::move(mDrainCb).Run(VideoDecoder::DecodeStatus::kOk);
setState(State::Idle);
@@ -422,21 +455,6 @@ void V4L2Decoder::serviceDeviceTask(bool event) {
}
}
-void V4L2Decoder::sendOutputBuffer(media::V4L2ReadableBufferRef buffer) {
- ALOGV("%s(bufferId=%zu)", __func__, buffer->BufferId());
- ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
-
- size_t bufferId = buffer->BufferId();
- auto it = mFrameAtDevice.find(bufferId);
- ALOG_ASSERT(it != mFrameAtDevice.end(), "buffer %zu is not found at mFrameAtDevice", bufferId);
- auto block = std::move(it->second);
- mFrameAtDevice.erase(it);
-
- block->setBitstreamId(buffer->GetTimeStamp().tv_sec);
- block->setVisibleRect(mVisibleRect);
- mOutputCb.Run(std::move(block));
-}
-
bool V4L2Decoder::dequeueResolutionChangeEvent() {
ALOGV("%s()", __func__);
ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
@@ -502,8 +520,6 @@ void V4L2Decoder::tryFetchVideoFrame() {
ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
ALOG_ASSERT(mVideoFramePool, "mVideoFramePool is null, haven't get the instance yet?");
- if (mState == State::Idle) return;
-
if (mOutputQueue->FreeBuffersCount() == 0) {
ALOGD("No free V4L2 output buffers, ignore.");
return;
@@ -558,7 +574,12 @@ void V4L2Decoder::onVideoFrameReady(
uint32_t v4l2Id = outputBuffer->BufferId();
ALOGV("QBUF to output queue, blockId=%u, V4L2Id=%u", blockId, v4l2Id);
- std::move(*outputBuffer).QueueDMABuf(frame->getFDs());
+ if (!std::move(*outputBuffer).QueueDMABuf(frame->getFDs())) {
+ ALOGE("%s(): Failed to QBUF to output queue, blockId=%u, V4L2Id=%u", __func__, blockId,
+ v4l2Id);
+ onError();
+ return;
+ }
if (mFrameAtDevice.find(v4l2Id) != mFrameAtDevice.end()) {
ALOGE("%s(): V4L2 buffer %d already enqueued.", __func__, v4l2Id);
onError();
diff --git a/components/include/v4l2_codec2/components/V4L2Decoder.h b/components/include/v4l2_codec2/components/V4L2Decoder.h
index 5539042..bdddc7f 100644
--- a/components/include/v4l2_codec2/components/V4L2Decoder.h
+++ b/components/include/v4l2_codec2/components/V4L2Decoder.h
@@ -62,7 +62,6 @@ private:
void pumpDecodeRequest();
void serviceDeviceTask(bool event);
- void sendOutputBuffer(media::V4L2ReadableBufferRef buffer);
bool dequeueResolutionChangeEvent();
bool changeResolution();
diff --git a/tests/c2_e2e_test/src/org/chromium/c2/test/E2eTestActivity.java b/tests/c2_e2e_test/src/org/chromium/c2/test/E2eTestActivity.java
index e423fc2..140ff82 100644
--- a/tests/c2_e2e_test/src/org/chromium/c2/test/E2eTestActivity.java
+++ b/tests/c2_e2e_test/src/org/chromium/c2/test/E2eTestActivity.java
@@ -29,6 +29,8 @@ public class E2eTestActivity extends Activity implements SurfaceHolder.Callback
private SurfaceView mSurfaceView;
private Size mSize;
+ private boolean mSurfaceCreated = false;
+ private boolean mCanStartTest = false;
private Size mExpectedSize;
private CountDownLatch mLatch;
@@ -44,6 +46,8 @@ public class E2eTestActivity extends Activity implements SurfaceHolder.Callback
mSurfaceView = (SurfaceView) findViewById(R.id.surface);
mSurfaceView.getHolder().addCallback(this);
+
+ mCanStartTest = !getIntent().getBooleanExtra("delay-start", false);
}
@Override
@@ -55,6 +59,14 @@ public class E2eTestActivity extends Activity implements SurfaceHolder.Callback
@Override
public void surfaceCreated(SurfaceHolder holder) {
+ mSurfaceCreated = true;
+ maybeStartTest();
+ }
+
+ private void maybeStartTest() {
+ if (!mSurfaceCreated || !mCanStartTest) {
+ return;
+ }
boolean encode = getIntent().getBooleanExtra("do-encode", false);
String[] testArgs =
getIntent().getStringArrayExtra("test-args") != null
@@ -71,7 +83,7 @@ public class E2eTestActivity extends Activity implements SurfaceHolder.Callback
encode,
testArgs,
testArgs.length,
- holder.getSurface(),
+ mSurfaceView.getHolder().getSurface(),
logFile);
Log.i(TAG, "Test returned result code " + res);
@@ -95,6 +107,12 @@ public class E2eTestActivity extends Activity implements SurfaceHolder.Callback
@Override
public void onNewIntent(Intent intent) {
+ if (intent.getAction().equals("org.chromium.c2.test.START_TEST")) {
+ mCanStartTest = true;
+ maybeStartTest();
+ return;
+ }
+
synchronized (this) {
if (mDecoderPtr != 0) {
stopDecoderLoop(mDecoderPtr);