From 983f81403e9189c52e23f878c6ea5d22e97448e2 Mon Sep 17 00:00:00 2001 From: Shuzhen Wang Date: Wed, 25 Sep 2019 14:19:28 -0700 Subject: [PATCH 1/3] Camera: Heic: Wait for first output tile callback before muxer start In order for muxer to start writing any track, the format returned from onFormatChanged must first be available. By waiting for first output tile callback, we are guaranteed to have received onFormatChanged, which means a valid format is available for muxer to use. This change also makes it such that no multiple muxers are inflight, avoiding dequeueBuffer failure because right now we only support maximum dequeued buffer count to be 1. Add more verbose logs for ease of debugging. Test: Vendor testing Bug: 141169323 Change-Id: I16fd11f5558e525ceae59df00533553e4b4e7589 Merged-In: I16fd11f5558e525ceae59df00533553e4b4e7589 (cherry picked from commit 3d00ee51a207d15718fcac4fefc72306532d68af) --- .../api2/HeicCompositeStream.cpp | 95 +++++++++++++------ .../api2/HeicCompositeStream.h | 7 +- 2 files changed, 70 insertions(+), 32 deletions(-) diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp index 052112a821..7663bb91ee 100644 --- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp +++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -66,7 +65,8 @@ HeicCompositeStream::HeicCompositeStream(wp device, mMainImageSurfaceId(-1), mYuvBufferAcquired(false), mProducerListener(new ProducerListener()), - mOutputBufferCounter(0), + mDequeuedOutputBufferCnt(0), + mCodecOutputCounter(0), mGridTimestampUs(0) { } @@ -231,6 +231,8 @@ void HeicCompositeStream::onBufferReleased(const BufferInfo& bufferInfo) { if (bufferInfo.mError) return; mCodecOutputBufferTimestamps.push(bufferInfo.mTimestamp); + ALOGV("%s: [%" PRId64 "]: Adding codecOutputBufferTimestamp (%zu timestamps in total)", + __FUNCTION__, bufferInfo.mTimestamp, mCodecOutputBufferTimestamps.size()); } // We need to get the settings early to handle the case where the codec output @@ -361,6 +363,8 @@ void HeicCompositeStream::onHeicOutputFrameAvailable( mCodecOutputBuffers.push_back(outputBufferInfo); mInputReadyCondition.signal(); } else { + ALOGV("%s: Releasing output buffer: size %d flags: 0x%x ", __FUNCTION__, + outputBufferInfo.size, outputBufferInfo.flags); mCodec->releaseOutputBuffer(outputBufferInfo.index); } } else { @@ -414,8 +418,10 @@ void HeicCompositeStream::onHeicFormatChanged(sp& newFormat) { mNumOutputTiles = 1; } - ALOGV("%s: mNumOutputTiles is %zu", __FUNCTION__, mNumOutputTiles); mFormat = newFormat; + + ALOGV("%s: mNumOutputTiles is %zu", __FUNCTION__, mNumOutputTiles); + mInputReadyCondition.signal(); } void HeicCompositeStream::onHeicCodecError() { @@ -459,9 +465,8 @@ status_t HeicCompositeStream::configureStream() { // Cannot use SourceSurface buffer count since it could be codec's 512*512 tile // buffer count. - int maxProducerBuffers = 1; if ((res = native_window_set_buffer_count( - anwConsumer, maxProducerBuffers + maxConsumerBuffers)) != OK) { + anwConsumer, kMaxOutputSurfaceProducerCount + maxConsumerBuffers)) != OK) { ALOGE("%s: Unable to set buffer count for stream %d", __FUNCTION__, mMainImageStreamId); return res; } @@ -505,6 +510,8 @@ void HeicCompositeStream::onShutter(const CaptureResultExtras& resultExtras, nse } if (mSettingsByFrameNumber.find(resultExtras.frameNumber) != mSettingsByFrameNumber.end()) { + ALOGV("%s: [%" PRId64 "]: frameNumber %" PRId64, __FUNCTION__, + timestamp, resultExtras.frameNumber); mFrameNumberMap.emplace(resultExtras.frameNumber, timestamp); mSettingsByTimestamp[timestamp] = mSettingsByFrameNumber[resultExtras.frameNumber]; mSettingsByFrameNumber.erase(resultExtras.frameNumber); @@ -593,13 +600,15 @@ void HeicCompositeStream::compilePendingInputLocked() { } else { // Direct mapping between camera timestamp (in ns) and codec timestamp (in us). bufferTime = mCodecOutputBufferTimestamps.front(); - mOutputBufferCounter++; - if (mOutputBufferCounter == mNumOutputTiles) { + mCodecOutputCounter++; + if (mCodecOutputCounter == mNumOutputTiles) { mCodecOutputBufferTimestamps.pop(); - mOutputBufferCounter = 0; + mCodecOutputCounter = 0; } mPendingInputFrames[bufferTime].codecOutputBuffers.push_back(*it); + ALOGV("%s: [%" PRId64 "]: Pushing codecOutputBuffers (time %" PRId64 " us)", + __FUNCTION__, bufferTime, it->timeUs); } mCodecOutputBuffers.erase(it); } @@ -607,6 +616,7 @@ void HeicCompositeStream::compilePendingInputLocked() { while (!mFrameNumberMap.empty()) { auto it = mFrameNumberMap.begin(); mPendingInputFrames[it->second].frameNumber = it->first; + ALOGV("%s: [%" PRId64 "]: frameNumber is %" PRId64, __FUNCTION__, it->second, it->first); mFrameNumberMap.erase(it); } @@ -675,16 +685,29 @@ bool HeicCompositeStream::getNextReadyInputLocked(int64_t *currentTs /*out*/) { } bool newInputAvailable = false; - for (const auto& it : mPendingInputFrames) { + for (auto& it : mPendingInputFrames) { + // New input is considered to be available only if: + // 1. input buffers are ready, or + // 2. App segment and muxer is created, or + // 3. A codec output tile is ready, and an output buffer is available. + // This makes sure that muxer gets created only when an output tile is + // generated, because right now we only handle 1 HEIC output buffer at a + // time (max dequeued buffer count is 1). bool appSegmentReady = (it.second.appSegmentBuffer.data != nullptr) && - !it.second.appSegmentWritten && it.second.result != nullptr; + !it.second.appSegmentWritten && it.second.result != nullptr && + it.second.muxer != nullptr; bool codecOutputReady = !it.second.codecOutputBuffers.empty(); bool codecInputReady = (it.second.yuvBuffer.data != nullptr) && (!it.second.codecInputBuffers.empty()); + bool hasOutputBuffer = it.second.muxer != nullptr || + (mDequeuedOutputBufferCnt < kMaxOutputSurfaceProducerCount); if ((!it.second.error) && (it.first < *currentTs) && - (appSegmentReady || codecOutputReady || codecInputReady)) { + (appSegmentReady || (codecOutputReady && hasOutputBuffer) || codecInputReady)) { *currentTs = it.first; + if (it.second.format == nullptr && mFormat != nullptr) { + it.second.format = mFormat->dup(); + } newInputAvailable = true; break; } @@ -716,15 +739,17 @@ status_t HeicCompositeStream::processInputFrame(nsecs_t timestamp, status_t res = OK; bool appSegmentReady = inputFrame.appSegmentBuffer.data != nullptr && - !inputFrame.appSegmentWritten && inputFrame.result != nullptr; + !inputFrame.appSegmentWritten && inputFrame.result != nullptr && + inputFrame.muxer != nullptr; bool codecOutputReady = inputFrame.codecOutputBuffers.size() > 0; bool codecInputReady = inputFrame.yuvBuffer.data != nullptr && - !inputFrame.codecInputBuffers.empty(); + !inputFrame.codecInputBuffers.empty(); + bool hasOutputBuffer = inputFrame.muxer != nullptr || + (mDequeuedOutputBufferCnt < kMaxOutputSurfaceProducerCount); - if (!appSegmentReady && !codecOutputReady && !codecInputReady) { - ALOGW("%s: No valid appSegmentBuffer/codec input/outputBuffer available!", __FUNCTION__); - return OK; - } + ALOGV("%s: [%" PRId64 "]: appSegmentReady %d, codecOutputReady %d, codecInputReady %d," + " dequeuedOutputBuffer %d", __FUNCTION__, timestamp, appSegmentReady, + codecOutputReady, codecInputReady, mDequeuedOutputBufferCnt); // Handle inputs for Hevc tiling if (codecInputReady) { @@ -736,7 +761,13 @@ status_t HeicCompositeStream::processInputFrame(nsecs_t timestamp, } } - // Initialize and start muxer if not yet done so + if (!(codecOutputReady && hasOutputBuffer) && !appSegmentReady) { + return OK; + } + + // Initialize and start muxer if not yet done so. In this case, + // codecOutputReady must be true. Otherwise, appSegmentReady is guaranteed + // to be false, and the function must have returned early. if (inputFrame.muxer == nullptr) { res = startMuxerForInputFrame(timestamp, inputFrame); if (res != OK) { @@ -747,7 +778,7 @@ status_t HeicCompositeStream::processInputFrame(nsecs_t timestamp, } // Write JPEG APP segments data to the muxer. - if (appSegmentReady && inputFrame.muxer != nullptr) { + if (appSegmentReady) { res = processAppSegment(timestamp, inputFrame); if (res != OK) { ALOGE("%s: Failed to process JPEG APP segments: %s (%d)", __FUNCTION__, @@ -780,11 +811,6 @@ status_t HeicCompositeStream::processInputFrame(nsecs_t timestamp, status_t HeicCompositeStream::startMuxerForInputFrame(nsecs_t timestamp, InputFrame &inputFrame) { sp outputANW = mOutputSurface; - if (inputFrame.codecOutputBuffers.size() == 0) { - // No single codec output buffer has been generated. Continue to - // wait. - return OK; - } auto res = outputANW->dequeueBuffer(mOutputSurface.get(), &inputFrame.anb, &inputFrame.fenceFd); if (res != OK) { @@ -792,6 +818,7 @@ status_t HeicCompositeStream::startMuxerForInputFrame(nsecs_t timestamp, InputFr res); return res; } + mDequeuedOutputBufferCnt++; // Combine current thread id, stream id and timestamp to uniquely identify image. std::ostringstream tempOutputFile; @@ -828,7 +855,7 @@ status_t HeicCompositeStream::startMuxerForInputFrame(nsecs_t timestamp, InputFr } } - ssize_t trackId = inputFrame.muxer->addTrack(mFormat); + ssize_t trackId = inputFrame.muxer->addTrack(inputFrame.format); if (trackId < 0) { ALOGE("%s: Failed to addTrack to the muxer: %zd", __FUNCTION__, trackId); return NO_INIT; @@ -844,6 +871,8 @@ status_t HeicCompositeStream::startMuxerForInputFrame(nsecs_t timestamp, InputFr return res; } + ALOGV("%s: [%" PRId64 "]: Muxer started for inputFrame", __FUNCTION__, + timestamp); return OK; } @@ -852,9 +881,6 @@ status_t HeicCompositeStream::processAppSegment(nsecs_t timestamp, InputFrame &i auto appSegmentSize = findAppSegmentsSize(inputFrame.appSegmentBuffer.data, inputFrame.appSegmentBuffer.width * inputFrame.appSegmentBuffer.height, &app1Size); - ALOGV("%s: appSegmentSize is %zu, width %d, height %d, app1Size %zu", __FUNCTION__, - appSegmentSize, inputFrame.appSegmentBuffer.width, - inputFrame.appSegmentBuffer.height, app1Size); if (appSegmentSize == 0) { ALOGE("%s: Failed to find JPEG APP segment size", __FUNCTION__); return NO_INIT; @@ -912,6 +938,9 @@ status_t HeicCompositeStream::processAppSegment(nsecs_t timestamp, InputFrame &i } inputFrame.appSegmentWritten = true; + ALOGV("%s: [%" PRId64 "]: appSegmentSize is %zu, width %d, height %d, app1Size %zu", + __FUNCTION__, timestamp, appSegmentSize, inputFrame.appSegmentBuffer.width, + inputFrame.appSegmentBuffer.height, app1Size); return OK; } @@ -934,8 +963,9 @@ status_t HeicCompositeStream::processCodecInputFrame(InputFrame &inputFrame) { mOutputWidth - tileX * mGridWidth : mGridWidth; size_t height = (tileY == static_cast(mGridRows) - 1) ? mOutputHeight - tileY * mGridHeight : mGridHeight; - ALOGV("%s: inputBuffer tileIndex [%zu, %zu], top %zu, left %zu, width %zu, height %zu", - __FUNCTION__, tileX, tileY, top, left, width, height); + ALOGV("%s: inputBuffer tileIndex [%zu, %zu], top %zu, left %zu, width %zu, height %zu," + " timeUs %" PRId64, __FUNCTION__, tileX, tileY, top, left, width, height, + inputBuffer.timeUs); res = copyOneYuvTile(buffer, inputFrame.yuvBuffer, top, left, width, height); if (res != OK) { @@ -990,6 +1020,9 @@ status_t HeicCompositeStream::processOneCodecOutputFrame(nsecs_t timestamp, } inputFrame.codecOutputBuffers.erase(inputFrame.codecOutputBuffers.begin()); + + ALOGV("%s: [%" PRId64 "]: Output buffer index %d", + __FUNCTION__, timestamp, it->index); return OK; } @@ -1046,7 +1079,9 @@ status_t HeicCompositeStream::processCompletedInputFrame(nsecs_t timestamp, return res; } inputFrame.anb = nullptr; + mDequeuedOutputBufferCnt--; + ALOGV("%s: [%" PRId64 "]", __FUNCTION__, timestamp); ATRACE_ASYNC_END("HEIC capture", inputFrame.frameNumber); return OK; } diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.h b/services/camera/libcameraservice/api2/HeicCompositeStream.h index 260c68e081..9bec90983e 100644 --- a/services/camera/libcameraservice/api2/HeicCompositeStream.h +++ b/services/camera/libcameraservice/api2/HeicCompositeStream.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -157,6 +158,7 @@ private: bool errorNotified; int64_t frameNumber; + sp format; sp muxer; int fenceFd; int fileFd; @@ -218,9 +220,10 @@ private: sp mMainImageConsumer; // Only applicable for HEVC codec. bool mYuvBufferAcquired; // Only applicable to HEVC codec + static const int32_t kMaxOutputSurfaceProducerCount = 1; sp mOutputSurface; sp mProducerListener; - + int32_t mDequeuedOutputBufferCnt; // Map from frame number to JPEG setting of orientation+quality std::map> mSettingsByFrameNumber; @@ -233,7 +236,7 @@ private: // Keep all incoming HEIC blob buffer pending further processing. std::vector mCodecOutputBuffers; std::queue mCodecOutputBufferTimestamps; - size_t mOutputBufferCounter; + size_t mCodecOutputCounter; // Keep all incoming Yuv buffer pending tiling and encoding (for HEVC YUV tiling only) std::vector mInputYuvBuffers; From 0017f0d7714fd06bfbc8faf3039f5fac8c3bdef4 Mon Sep 17 00:00:00 2001 From: Michael Gonzalez Date: Wed, 9 Oct 2019 15:38:17 -0700 Subject: [PATCH 2/3] Camera: Heic: Handle out-of-order buffer outputs During reprocess usecases, the Camera HAL may return JPEG Appsegment frames out of order. This leads to a scenario where mAppSegmentConsumer->lockNextBuffer may not refer to the currently muxed frame. To work around this, the number of lockable appsegment buffers has been increased. Test: Vendor testing Bug: 141169323 Change-Id: Ia498f6ddaba588b66cbaeee94fe8bdd7314bb90c Merged-In: Ia498f6ddaba588b66cbaeee94fe8bdd7314bb90c (cherry picked from commit b5986a36b2913ec100b110720c3e24e26fd0d1dd) --- .../api2/HeicCompositeStream.cpp | 56 +++++++++++-------- .../api2/HeicCompositeStream.h | 7 ++- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp index 7663bb91ee..dc46285af6 100644 --- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp +++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp @@ -60,12 +60,12 @@ HeicCompositeStream::HeicCompositeStream(wp device, mUseGrid(false), mAppSegmentStreamId(-1), mAppSegmentSurfaceId(-1), - mAppSegmentBufferAcquired(false), mMainImageStreamId(-1), mMainImageSurfaceId(-1), mYuvBufferAcquired(false), mProducerListener(new ProducerListener()), mDequeuedOutputBufferCnt(0), + mLockedAppSegmentBufferCnt(0), mCodecOutputCounter(0), mGridTimestampUs(0) { } @@ -132,7 +132,7 @@ status_t HeicCompositeStream::createInternalStreams(const std::vector producer; sp consumer; BufferQueue::createBufferQueue(&producer, &consumer); - mAppSegmentConsumer = new CpuConsumer(consumer, 1); + mAppSegmentConsumer = new CpuConsumer(consumer, kMaxAcquiredAppSegment); mAppSegmentConsumer->setFrameAvailableListener(this); mAppSegmentConsumer->setName(String8("Camera3-HeicComposite-AppSegmentStream")); mAppSegmentSurface = new Surface(producer); @@ -527,12 +527,12 @@ void HeicCompositeStream::compilePendingInputLocked() { mSettingsByTimestamp.erase(it); } - while (!mInputAppSegmentBuffers.empty() && !mAppSegmentBufferAcquired) { + while (!mInputAppSegmentBuffers.empty()) { CpuConsumer::LockedBuffer imgBuffer; auto it = mInputAppSegmentBuffers.begin(); auto res = mAppSegmentConsumer->lockNextBuffer(&imgBuffer); if (res == NOT_ENOUGH_DATA) { - // Canot not lock any more buffers. + // Can not lock any more buffers. break; } else if ((res != OK) || (*it != imgBuffer.timestamp)) { if (res != OK) { @@ -542,6 +542,7 @@ void HeicCompositeStream::compilePendingInputLocked() { ALOGE("%s: Expecting JPEG_APP_SEGMENTS buffer with time stamp: %" PRId64 " received buffer with time stamp: %" PRId64, __FUNCTION__, *it, imgBuffer.timestamp); + mAppSegmentConsumer->unlockBuffer(imgBuffer); } mPendingInputFrames[*it].error = true; mInputAppSegmentBuffers.erase(it); @@ -553,7 +554,7 @@ void HeicCompositeStream::compilePendingInputLocked() { mAppSegmentConsumer->unlockBuffer(imgBuffer); } else { mPendingInputFrames[imgBuffer.timestamp].appSegmentBuffer = imgBuffer; - mAppSegmentBufferAcquired = true; + mLockedAppSegmentBufferCnt++; } mInputAppSegmentBuffers.erase(it); } @@ -563,7 +564,7 @@ void HeicCompositeStream::compilePendingInputLocked() { auto it = mInputYuvBuffers.begin(); auto res = mMainImageConsumer->lockNextBuffer(&imgBuffer); if (res == NOT_ENOUGH_DATA) { - // Canot not lock any more buffers. + // Can not lock any more buffers. break; } else if (res != OK) { ALOGE("%s: Error locking YUV_888 image buffer: %s (%d)", __FUNCTION__, @@ -797,12 +798,18 @@ status_t HeicCompositeStream::processInputFrame(nsecs_t timestamp, } } - if (inputFrame.appSegmentWritten && inputFrame.pendingOutputTiles == 0) { - res = processCompletedInputFrame(timestamp, inputFrame); - if (res != OK) { - ALOGE("%s: Failed to process completed input frame: %s (%d)", __FUNCTION__, - strerror(-res), res); - return res; + if (inputFrame.pendingOutputTiles == 0) { + if (inputFrame.appSegmentWritten) { + res = processCompletedInputFrame(timestamp, inputFrame); + if (res != OK) { + ALOGE("%s: Failed to process completed input frame: %s (%d)", __FUNCTION__, + strerror(-res), res); + return res; + } + } else if (mLockedAppSegmentBufferCnt == kMaxAcquiredAppSegment) { + ALOGE("%s: Out-of-order app segment buffers reaches limit %u", __FUNCTION__, + kMaxAcquiredAppSegment); + return INVALID_OPERATION; } } @@ -936,11 +943,17 @@ status_t HeicCompositeStream::processAppSegment(nsecs_t timestamp, InputFrame &i __FUNCTION__, strerror(-res), res); return res; } - inputFrame.appSegmentWritten = true; ALOGV("%s: [%" PRId64 "]: appSegmentSize is %zu, width %d, height %d, app1Size %zu", __FUNCTION__, timestamp, appSegmentSize, inputFrame.appSegmentBuffer.width, inputFrame.appSegmentBuffer.height, app1Size); + + inputFrame.appSegmentWritten = true; + // Release the buffer now so any pending input app segments can be processed + mAppSegmentConsumer->unlockBuffer(inputFrame.appSegmentBuffer); + inputFrame.appSegmentBuffer.data = nullptr; + mLockedAppSegmentBufferCnt--; + return OK; } @@ -1095,7 +1108,6 @@ void HeicCompositeStream::releaseInputFrameLocked(InputFrame *inputFrame /*out*/ if (inputFrame->appSegmentBuffer.data != nullptr) { mAppSegmentConsumer->unlockBuffer(inputFrame->appSegmentBuffer); inputFrame->appSegmentBuffer.data = nullptr; - mAppSegmentBufferAcquired = false; } while (!inputFrame->codecOutputBuffers.empty()) { @@ -1133,11 +1145,13 @@ void HeicCompositeStream::releaseInputFrameLocked(InputFrame *inputFrame /*out*/ } } -void HeicCompositeStream::releaseInputFramesLocked(int64_t currentTs) { +void HeicCompositeStream::releaseInputFramesLocked() { auto it = mPendingInputFrames.begin(); while (it != mPendingInputFrames.end()) { - if (it->first <= currentTs) { - releaseInputFrameLocked(&it->second); + auto& inputFrame = it->second; + if (inputFrame.error || + (inputFrame.appSegmentWritten && inputFrame.pendingOutputTiles == 0)) { + releaseInputFrameLocked(&inputFrame); it = mPendingInputFrames.erase(it); } else { it++; @@ -1541,7 +1555,7 @@ bool HeicCompositeStream::threadLoop() { // In case we landed in error state, return any pending buffers and // halt all further processing. compilePendingInputLocked(); - releaseInputFramesLocked(currentTs); + releaseInputFramesLocked(); return false; } @@ -1583,11 +1597,7 @@ bool HeicCompositeStream::threadLoop() { mPendingInputFrames[currentTs].error = true; } - if (mPendingInputFrames[currentTs].error || - (mPendingInputFrames[currentTs].appSegmentWritten && - mPendingInputFrames[currentTs].pendingOutputTiles == 0)) { - releaseInputFramesLocked(currentTs); - } + releaseInputFramesLocked(); return true; } diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.h b/services/camera/libcameraservice/api2/HeicCompositeStream.h index 9bec90983e..04e7b83c20 100644 --- a/services/camera/libcameraservice/api2/HeicCompositeStream.h +++ b/services/camera/libcameraservice/api2/HeicCompositeStream.h @@ -189,7 +189,7 @@ private: status_t processCompletedInputFrame(nsecs_t timestamp, InputFrame &inputFrame); void releaseInputFrameLocked(InputFrame *inputFrame /*out*/); - void releaseInputFramesLocked(int64_t currentTs); + void releaseInputFramesLocked(); size_t findAppSegmentsSize(const uint8_t* appSegmentBuffer, size_t maxSize, size_t* app1SegmentSize); @@ -207,11 +207,13 @@ private: static_cast(HAL_DATASPACE_JPEG_APP_SEGMENTS); static const android_dataspace kHeifDataSpace = static_cast(HAL_DATASPACE_HEIF); + // Use the limit of pipeline depth in the API sepc as maximum number of acquired + // app segment buffers. + static const uint32_t kMaxAcquiredAppSegment = 8; int mAppSegmentStreamId, mAppSegmentSurfaceId; sp mAppSegmentConsumer; sp mAppSegmentSurface; - bool mAppSegmentBufferAcquired; size_t mAppSegmentMaxSize; CameraMetadata mStaticInfo; @@ -232,6 +234,7 @@ private: // Keep all incoming APP segment Blob buffer pending further processing. std::vector mInputAppSegmentBuffers; + int32_t mLockedAppSegmentBufferCnt; // Keep all incoming HEIC blob buffer pending further processing. std::vector mCodecOutputBuffers; From f2ae75ddc535e8ecb253d0b657e597c227057838 Mon Sep 17 00:00:00 2001 From: Michael Gonzalez Date: Tue, 8 Oct 2019 14:30:32 -0700 Subject: [PATCH 3/3] Camera: Heic: Wait for output TS before dequeuing output buffers During testHeicExif, the codec output buffer timestamp may rarely arrive after the first codec output tiles arrive. Test: vendor testing Bug: 141169323 Change-Id: Iba1c82b087533cb87a32d69f7d6908e2c925b807 Merged-In: Iba1c82b087533cb87a32d69f7d6908e2c925b807 (cherry picked from commit 5c103f2962cd41a948dca4f2156c6efdf506bef1) --- services/camera/libcameraservice/api2/HeicCompositeStream.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp index dc46285af6..9f15be02f7 100644 --- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp +++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp @@ -597,7 +597,8 @@ void HeicCompositeStream::compilePendingInputLocked() { // to look up timestamp. int64_t bufferTime = -1; if (mCodecOutputBufferTimestamps.empty()) { - ALOGE("%s: Failed to find buffer timestamp for codec output buffer!", __FUNCTION__); + ALOGV("%s: Failed to find buffer timestamp for codec output buffer!", __FUNCTION__); + break; } else { // Direct mapping between camera timestamp (in ns) and codec timestamp (in us). bufferTime = mCodecOutputBufferTimestamps.front();