Loading media/codec2/hal/client/client.cpp +137 −281 File changed.Preview size limit exceeded, changes collapsed. Show changes media/codec2/hal/client/include/codec2/hidl/client.h +13 −40 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <C2Param.h> #include <C2.h> #include <gui/FrameTimestamps.h> #include <gui/IGraphicBufferProducer.h> #include <hidl/HidlSupport.h> #include <utils/StrongPointer.h> Loading Loading @@ -83,13 +84,6 @@ struct IComponent; struct IComponentStore; } // namespace android::hardware::media::c2::V1_2 namespace aidl::android::hardware::media::c2 { class IComponent; class IComponentInterface; class IComponentStore; class IConfigurable; } // namespace aidl::android::hardware::media::c2 namespace android::hardware::media::bufferpool::V2_0 { struct IClientManager; } // namespace android::hardware::media::bufferpool::V2_0 Loading @@ -112,34 +106,7 @@ namespace android { // declaration of an inner class is not possible. struct Codec2ConfigurableClient { typedef ::android::hardware::media::c2::V1_0::IConfigurable HidlBase; struct ImplBase { virtual ~ImplBase() = default; virtual const C2String& getName() const = 0; virtual c2_status_t query( const std::vector<C2Param*>& stackParams, const std::vector<C2Param::Index> &heapParamIndices, c2_blocking_t mayBlock, std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0; virtual c2_status_t config( const std::vector<C2Param*> ¶ms, c2_blocking_t mayBlock, std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0; virtual c2_status_t querySupportedParams( std::vector<std::shared_ptr<C2ParamDescriptor>>* const params ) const = 0; virtual c2_status_t querySupportedValues( std::vector<C2FieldSupportedValuesQuery>& fields, c2_blocking_t mayBlock) const = 0; }; explicit Codec2ConfigurableClient(const sp<HidlBase> &hidlBase); typedef ::android::hardware::media::c2::V1_0::IConfigurable Base; const C2String& getName() const; Loading @@ -161,11 +128,15 @@ struct Codec2ConfigurableClient { c2_status_t querySupportedValues( std::vector<C2FieldSupportedValuesQuery>& fields, c2_blocking_t mayBlock) const; private: struct HidlImpl; struct AidlImpl; const std::unique_ptr<ImplBase> mImpl; // base cannot be null. Codec2ConfigurableClient(const sp<Base>& base); protected: sp<Base> mBase; C2String mName; friend struct Codec2Client; }; struct Codec2Client : public Codec2ConfigurableClient { Loading Loading @@ -438,6 +409,9 @@ struct Codec2Client::Component : public Codec2Client::Configurable { const QueueBufferInput& input, QueueBufferOutput* output); // Retrieve frame event history from the output surface. void pollForRenderedFrames(FrameEventHistoryDelta* delta); // Set max dequeue count for output surface. void setOutputSurfaceMaxDequeueCount(int maxDequeueCount); Loading Loading @@ -538,4 +512,3 @@ protected: } // namespace android #endif // CODEC2_HIDL_CLIENT_H media/codec2/hal/client/include/codec2/hidl/output.h +4 −6 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #ifndef CODEC2_HIDL_V1_0_UTILS_OUTPUT_BUFFER_QUEUE #define CODEC2_HIDL_V1_0_UTILS_OUTPUT_BUFFER_QUEUE #include <gui/FrameTimestamps.h> #include <gui/IGraphicBufferProducer.h> #include <codec2/hidl/1.0/types.h> #include <codec2/hidl/1.2/types.h> Loading Loading @@ -50,10 +51,6 @@ struct OutputBufferQueue { int maxDequeueBufferCount, std::shared_ptr<V1_2::SurfaceSyncObj> *syncObj); // If there are waiters to allocate from the old surface, wake up and expire // them. void expireOldWaiters(); // Stop using the current output surface. Pending buffer opeations will not // perform anymore. void stop(); Loading @@ -64,6 +61,9 @@ struct OutputBufferQueue { const BnGraphicBufferProducer::QueueBufferInput& input, BnGraphicBufferProducer::QueueBufferOutput* output); // Retrieve frame event history from the output surface. void pollForRenderedFrames(FrameEventHistoryDelta* delta); // Call holdBufferQueueBlock() on output blocks in the given workList. // The OutputBufferQueue will take the ownership of output blocks. // Loading @@ -90,8 +90,6 @@ private: std::weak_ptr<_C2BlockPoolData> mPoolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS]; std::shared_ptr<C2SurfaceSyncMemory> mSyncMem; bool mStopped; std::mutex mOldMutex; std::shared_ptr<C2SurfaceSyncMemory> mOldMem; bool registerBuffer(const C2ConstGraphicBlock& block); }; Loading media/codec2/hal/client/output.cpp +7 −18 Original line number Diff line number Diff line Loading @@ -217,7 +217,6 @@ bool OutputBufferQueue::configure(const sp<IGraphicBufferProducer>& igbp, sp<GraphicBuffer> buffers[BufferQueueDefs::NUM_BUFFER_SLOTS]; std::weak_ptr<_C2BlockPoolData> poolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS]; std::shared_ptr<C2SurfaceSyncMemory> oldMem; { std::scoped_lock<std::mutex> l(mMutex); bool stopped = mStopped; Loading @@ -239,7 +238,7 @@ bool OutputBufferQueue::configure(const sp<IGraphicBufferProducer>& igbp, } return false; } oldMem = mSyncMem; std::shared_ptr<C2SurfaceSyncMemory> oldMem = mSyncMem; C2SyncVariables *oldSync = mSyncMem ? mSyncMem->mem() : nullptr; if (oldSync) { oldSync->lock(); Loading Loading @@ -315,26 +314,11 @@ bool OutputBufferQueue::configure(const sp<IGraphicBufferProducer>& igbp, newSync->unlock(); } } { std::scoped_lock<std::mutex> l(mOldMutex); mOldMem = oldMem; } ALOGD("remote graphic buffer migration %zu/%zu", success, tryNum); return true; } void OutputBufferQueue::expireOldWaiters() { std::scoped_lock<std::mutex> l(mOldMutex); if (mOldMem) { C2SyncVariables *oldSync = mOldMem->mem(); if (oldSync) { oldSync->notifyAll(); } mOldMem.reset(); } } void OutputBufferQueue::stop() { std::scoped_lock<std::mutex> l(mMutex); mStopped = true; Loading Loading @@ -492,6 +476,12 @@ status_t OutputBufferQueue::outputBuffer( return OK; } void OutputBufferQueue::pollForRenderedFrames(FrameEventHistoryDelta* delta) { if (mIgbp) { mIgbp->getFrameTimestamps(delta); } } void OutputBufferQueue::holdBufferQueueBlocks( const std::list<std::unique_ptr<C2Work>>& workList) { forEachBlock(workList, Loading @@ -516,4 +506,3 @@ void OutputBufferQueue::updateMaxDequeueBufferCount(int maxDequeueBufferCount) { } // namespace media } // namespace hardware } // namespace android media/codec2/sfplugin/CCodecBufferChannel.cpp +106 −5 Original line number Diff line number Diff line Loading @@ -902,7 +902,7 @@ status_t CCodecBufferChannel::renderOutputBuffer( } // TODO: revisit this after C2Fence implementation. android::IGraphicBufferProducer::QueueBufferInput qbi( IGraphicBufferProducer::QueueBufferInput qbi( timestampNs, false, // droppable dataSpace, Loading Loading @@ -966,9 +966,9 @@ status_t CCodecBufferChannel::renderOutputBuffer( } SetMetadataToGralloc4Handle(dataSpace, hdrStaticInfo, hdrDynamicInfo, block.handle()); // we don't have dirty regions qbi.setSurfaceDamage(Region::INVALID_REGION); android::IGraphicBufferProducer::QueueBufferOutput qbo; qbi.setSurfaceDamage(Region::INVALID_REGION); // we don't have dirty regions qbi.getFrameTimestamps = true; // we need to know when a frame is rendered IGraphicBufferProducer::QueueBufferOutput qbo; status_t result = mComponent->queueToOutputSurface(block, qbi, &qbo); if (result != OK) { ALOGI("[%s] queueBuffer failed: %d", mName, result); Loading @@ -986,11 +986,107 @@ status_t CCodecBufferChannel::renderOutputBuffer( int64_t mediaTimeUs = 0; (void)buffer->meta()->findInt64("timeUs", &mediaTimeUs); mCCodecCallback->onOutputFramesRendered(mediaTimeUs, timestampNs); trackReleasedFrame(qbo, mediaTimeUs, timestampNs); processRenderedFrames(qbo.frameTimestamps); return OK; } void CCodecBufferChannel::initializeFrameTrackingFor(ANativeWindow * window) { int hasPresentFenceTimes = 0; window->query(window, NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &hasPresentFenceTimes); mHasPresentFenceTimes = hasPresentFenceTimes == 1; if (mHasPresentFenceTimes) { ALOGI("Using latch times for frame rendered signals - present fences not supported"); } mTrackedFrames.clear(); } void CCodecBufferChannel::trackReleasedFrame(const IGraphicBufferProducer::QueueBufferOutput& qbo, int64_t mediaTimeUs, int64_t desiredRenderTimeNs) { // If the render time is earlier than now, then we're suggesting it should be rendered ASAP, // so track the frame as if the desired render time is now. int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC); if (desiredRenderTimeNs < nowNs) { desiredRenderTimeNs = nowNs; } // We've just queued a frame to the surface, so keep track of it and later check to see if it is // actually rendered. TrackedFrame frame; frame.number = qbo.nextFrameNumber - 1; frame.mediaTimeUs = mediaTimeUs; frame.desiredRenderTimeNs = desiredRenderTimeNs; frame.latchTime = -1; frame.presentFence = nullptr; mTrackedFrames.push_back(frame); } void CCodecBufferChannel::processRenderedFrames(const FrameEventHistoryDelta& deltas) { // Grab the latch times and present fences from the frame event deltas for (const auto& delta : deltas) { for (auto& frame : mTrackedFrames) { if (delta.getFrameNumber() == frame.number) { delta.getLatchTime(&frame.latchTime); delta.getDisplayPresentFence(&frame.presentFence); } } } // Scan all frames and check to see if the frames that SHOULD have been rendered by now, have, // in fact, been rendered. int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC); while (!mTrackedFrames.empty()) { TrackedFrame & frame = mTrackedFrames.front(); // Frames that should have been rendered at least 100ms in the past are checked if (frame.desiredRenderTimeNs > nowNs - 100*1000*1000LL) { break; } // If we don't have a render time by now, then consider the frame as dropped int64_t renderTimeNs = getRenderTimeNs(frame); if (renderTimeNs != -1) { mCCodecCallback->onOutputFramesRendered(frame.mediaTimeUs, renderTimeNs); } mTrackedFrames.pop_front(); } } int64_t CCodecBufferChannel::getRenderTimeNs(const TrackedFrame& frame) { // If the device doesn't have accurate present fence times, then use the latch time as a proxy if (!mHasPresentFenceTimes) { if (frame.latchTime == -1) { ALOGD("no latch time for frame %d", (int) frame.number); return -1; } return frame.latchTime; } if (frame.presentFence == nullptr) { ALOGW("no present fence for frame %d", (int) frame.number); return -1; } nsecs_t actualRenderTimeNs = frame.presentFence->getSignalTime(); if (actualRenderTimeNs == Fence::SIGNAL_TIME_INVALID) { ALOGW("invalid signal time for frame %d", (int) frame.number); return -1; } if (actualRenderTimeNs == Fence::SIGNAL_TIME_PENDING) { ALOGD("present fence has not fired for frame %d", (int) frame.number); return -1; } return actualRenderTimeNs; } void CCodecBufferChannel::pollForRenderedBuffers() { FrameEventHistoryDelta delta; mComponent->pollForRenderedFrames(&delta); processRenderedFrames(delta); } status_t CCodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) { ALOGV("[%s] discardBuffer: %p", mName, buffer.get()); bool released = false; Loading Loading @@ -1615,6 +1711,8 @@ void CCodecBufferChannel::reset() { Mutexed<Output>::Locked output(mOutput); output->buffers.reset(); } // reset the frames that are being tracked for onFrameRendered callbacks mTrackedFrames.clear(); } void CCodecBufferChannel::release() { Loading Loading @@ -1683,6 +1781,8 @@ void CCodecBufferChannel::flush(const std::list<std::unique_ptr<C2Work>> &flushe output->buffers->flushStash(); } } // reset the frames that are being tracked for onFrameRendered callbacks mTrackedFrames.clear(); } void CCodecBufferChannel::onWorkDone( Loading Loading @@ -2162,6 +2262,7 @@ status_t CCodecBufferChannel::setSurface(const sp<Surface> &newSurface, bool pus Mutexed<OutputSurface>::Locked output(mOutputSurface); output->surface = newSurface; output->generation = generation; initializeFrameTrackingFor(static_cast<ANativeWindow *>(newSurface.get())); } if (oldSurface && pushBlankBuffer) { Loading Loading
media/codec2/hal/client/client.cpp +137 −281 File changed.Preview size limit exceeded, changes collapsed. Show changes
media/codec2/hal/client/include/codec2/hidl/client.h +13 −40 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <C2Param.h> #include <C2.h> #include <gui/FrameTimestamps.h> #include <gui/IGraphicBufferProducer.h> #include <hidl/HidlSupport.h> #include <utils/StrongPointer.h> Loading Loading @@ -83,13 +84,6 @@ struct IComponent; struct IComponentStore; } // namespace android::hardware::media::c2::V1_2 namespace aidl::android::hardware::media::c2 { class IComponent; class IComponentInterface; class IComponentStore; class IConfigurable; } // namespace aidl::android::hardware::media::c2 namespace android::hardware::media::bufferpool::V2_0 { struct IClientManager; } // namespace android::hardware::media::bufferpool::V2_0 Loading @@ -112,34 +106,7 @@ namespace android { // declaration of an inner class is not possible. struct Codec2ConfigurableClient { typedef ::android::hardware::media::c2::V1_0::IConfigurable HidlBase; struct ImplBase { virtual ~ImplBase() = default; virtual const C2String& getName() const = 0; virtual c2_status_t query( const std::vector<C2Param*>& stackParams, const std::vector<C2Param::Index> &heapParamIndices, c2_blocking_t mayBlock, std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0; virtual c2_status_t config( const std::vector<C2Param*> ¶ms, c2_blocking_t mayBlock, std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0; virtual c2_status_t querySupportedParams( std::vector<std::shared_ptr<C2ParamDescriptor>>* const params ) const = 0; virtual c2_status_t querySupportedValues( std::vector<C2FieldSupportedValuesQuery>& fields, c2_blocking_t mayBlock) const = 0; }; explicit Codec2ConfigurableClient(const sp<HidlBase> &hidlBase); typedef ::android::hardware::media::c2::V1_0::IConfigurable Base; const C2String& getName() const; Loading @@ -161,11 +128,15 @@ struct Codec2ConfigurableClient { c2_status_t querySupportedValues( std::vector<C2FieldSupportedValuesQuery>& fields, c2_blocking_t mayBlock) const; private: struct HidlImpl; struct AidlImpl; const std::unique_ptr<ImplBase> mImpl; // base cannot be null. Codec2ConfigurableClient(const sp<Base>& base); protected: sp<Base> mBase; C2String mName; friend struct Codec2Client; }; struct Codec2Client : public Codec2ConfigurableClient { Loading Loading @@ -438,6 +409,9 @@ struct Codec2Client::Component : public Codec2Client::Configurable { const QueueBufferInput& input, QueueBufferOutput* output); // Retrieve frame event history from the output surface. void pollForRenderedFrames(FrameEventHistoryDelta* delta); // Set max dequeue count for output surface. void setOutputSurfaceMaxDequeueCount(int maxDequeueCount); Loading Loading @@ -538,4 +512,3 @@ protected: } // namespace android #endif // CODEC2_HIDL_CLIENT_H
media/codec2/hal/client/include/codec2/hidl/output.h +4 −6 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #ifndef CODEC2_HIDL_V1_0_UTILS_OUTPUT_BUFFER_QUEUE #define CODEC2_HIDL_V1_0_UTILS_OUTPUT_BUFFER_QUEUE #include <gui/FrameTimestamps.h> #include <gui/IGraphicBufferProducer.h> #include <codec2/hidl/1.0/types.h> #include <codec2/hidl/1.2/types.h> Loading Loading @@ -50,10 +51,6 @@ struct OutputBufferQueue { int maxDequeueBufferCount, std::shared_ptr<V1_2::SurfaceSyncObj> *syncObj); // If there are waiters to allocate from the old surface, wake up and expire // them. void expireOldWaiters(); // Stop using the current output surface. Pending buffer opeations will not // perform anymore. void stop(); Loading @@ -64,6 +61,9 @@ struct OutputBufferQueue { const BnGraphicBufferProducer::QueueBufferInput& input, BnGraphicBufferProducer::QueueBufferOutput* output); // Retrieve frame event history from the output surface. void pollForRenderedFrames(FrameEventHistoryDelta* delta); // Call holdBufferQueueBlock() on output blocks in the given workList. // The OutputBufferQueue will take the ownership of output blocks. // Loading @@ -90,8 +90,6 @@ private: std::weak_ptr<_C2BlockPoolData> mPoolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS]; std::shared_ptr<C2SurfaceSyncMemory> mSyncMem; bool mStopped; std::mutex mOldMutex; std::shared_ptr<C2SurfaceSyncMemory> mOldMem; bool registerBuffer(const C2ConstGraphicBlock& block); }; Loading
media/codec2/hal/client/output.cpp +7 −18 Original line number Diff line number Diff line Loading @@ -217,7 +217,6 @@ bool OutputBufferQueue::configure(const sp<IGraphicBufferProducer>& igbp, sp<GraphicBuffer> buffers[BufferQueueDefs::NUM_BUFFER_SLOTS]; std::weak_ptr<_C2BlockPoolData> poolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS]; std::shared_ptr<C2SurfaceSyncMemory> oldMem; { std::scoped_lock<std::mutex> l(mMutex); bool stopped = mStopped; Loading @@ -239,7 +238,7 @@ bool OutputBufferQueue::configure(const sp<IGraphicBufferProducer>& igbp, } return false; } oldMem = mSyncMem; std::shared_ptr<C2SurfaceSyncMemory> oldMem = mSyncMem; C2SyncVariables *oldSync = mSyncMem ? mSyncMem->mem() : nullptr; if (oldSync) { oldSync->lock(); Loading Loading @@ -315,26 +314,11 @@ bool OutputBufferQueue::configure(const sp<IGraphicBufferProducer>& igbp, newSync->unlock(); } } { std::scoped_lock<std::mutex> l(mOldMutex); mOldMem = oldMem; } ALOGD("remote graphic buffer migration %zu/%zu", success, tryNum); return true; } void OutputBufferQueue::expireOldWaiters() { std::scoped_lock<std::mutex> l(mOldMutex); if (mOldMem) { C2SyncVariables *oldSync = mOldMem->mem(); if (oldSync) { oldSync->notifyAll(); } mOldMem.reset(); } } void OutputBufferQueue::stop() { std::scoped_lock<std::mutex> l(mMutex); mStopped = true; Loading Loading @@ -492,6 +476,12 @@ status_t OutputBufferQueue::outputBuffer( return OK; } void OutputBufferQueue::pollForRenderedFrames(FrameEventHistoryDelta* delta) { if (mIgbp) { mIgbp->getFrameTimestamps(delta); } } void OutputBufferQueue::holdBufferQueueBlocks( const std::list<std::unique_ptr<C2Work>>& workList) { forEachBlock(workList, Loading @@ -516,4 +506,3 @@ void OutputBufferQueue::updateMaxDequeueBufferCount(int maxDequeueBufferCount) { } // namespace media } // namespace hardware } // namespace android
media/codec2/sfplugin/CCodecBufferChannel.cpp +106 −5 Original line number Diff line number Diff line Loading @@ -902,7 +902,7 @@ status_t CCodecBufferChannel::renderOutputBuffer( } // TODO: revisit this after C2Fence implementation. android::IGraphicBufferProducer::QueueBufferInput qbi( IGraphicBufferProducer::QueueBufferInput qbi( timestampNs, false, // droppable dataSpace, Loading Loading @@ -966,9 +966,9 @@ status_t CCodecBufferChannel::renderOutputBuffer( } SetMetadataToGralloc4Handle(dataSpace, hdrStaticInfo, hdrDynamicInfo, block.handle()); // we don't have dirty regions qbi.setSurfaceDamage(Region::INVALID_REGION); android::IGraphicBufferProducer::QueueBufferOutput qbo; qbi.setSurfaceDamage(Region::INVALID_REGION); // we don't have dirty regions qbi.getFrameTimestamps = true; // we need to know when a frame is rendered IGraphicBufferProducer::QueueBufferOutput qbo; status_t result = mComponent->queueToOutputSurface(block, qbi, &qbo); if (result != OK) { ALOGI("[%s] queueBuffer failed: %d", mName, result); Loading @@ -986,11 +986,107 @@ status_t CCodecBufferChannel::renderOutputBuffer( int64_t mediaTimeUs = 0; (void)buffer->meta()->findInt64("timeUs", &mediaTimeUs); mCCodecCallback->onOutputFramesRendered(mediaTimeUs, timestampNs); trackReleasedFrame(qbo, mediaTimeUs, timestampNs); processRenderedFrames(qbo.frameTimestamps); return OK; } void CCodecBufferChannel::initializeFrameTrackingFor(ANativeWindow * window) { int hasPresentFenceTimes = 0; window->query(window, NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &hasPresentFenceTimes); mHasPresentFenceTimes = hasPresentFenceTimes == 1; if (mHasPresentFenceTimes) { ALOGI("Using latch times for frame rendered signals - present fences not supported"); } mTrackedFrames.clear(); } void CCodecBufferChannel::trackReleasedFrame(const IGraphicBufferProducer::QueueBufferOutput& qbo, int64_t mediaTimeUs, int64_t desiredRenderTimeNs) { // If the render time is earlier than now, then we're suggesting it should be rendered ASAP, // so track the frame as if the desired render time is now. int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC); if (desiredRenderTimeNs < nowNs) { desiredRenderTimeNs = nowNs; } // We've just queued a frame to the surface, so keep track of it and later check to see if it is // actually rendered. TrackedFrame frame; frame.number = qbo.nextFrameNumber - 1; frame.mediaTimeUs = mediaTimeUs; frame.desiredRenderTimeNs = desiredRenderTimeNs; frame.latchTime = -1; frame.presentFence = nullptr; mTrackedFrames.push_back(frame); } void CCodecBufferChannel::processRenderedFrames(const FrameEventHistoryDelta& deltas) { // Grab the latch times and present fences from the frame event deltas for (const auto& delta : deltas) { for (auto& frame : mTrackedFrames) { if (delta.getFrameNumber() == frame.number) { delta.getLatchTime(&frame.latchTime); delta.getDisplayPresentFence(&frame.presentFence); } } } // Scan all frames and check to see if the frames that SHOULD have been rendered by now, have, // in fact, been rendered. int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC); while (!mTrackedFrames.empty()) { TrackedFrame & frame = mTrackedFrames.front(); // Frames that should have been rendered at least 100ms in the past are checked if (frame.desiredRenderTimeNs > nowNs - 100*1000*1000LL) { break; } // If we don't have a render time by now, then consider the frame as dropped int64_t renderTimeNs = getRenderTimeNs(frame); if (renderTimeNs != -1) { mCCodecCallback->onOutputFramesRendered(frame.mediaTimeUs, renderTimeNs); } mTrackedFrames.pop_front(); } } int64_t CCodecBufferChannel::getRenderTimeNs(const TrackedFrame& frame) { // If the device doesn't have accurate present fence times, then use the latch time as a proxy if (!mHasPresentFenceTimes) { if (frame.latchTime == -1) { ALOGD("no latch time for frame %d", (int) frame.number); return -1; } return frame.latchTime; } if (frame.presentFence == nullptr) { ALOGW("no present fence for frame %d", (int) frame.number); return -1; } nsecs_t actualRenderTimeNs = frame.presentFence->getSignalTime(); if (actualRenderTimeNs == Fence::SIGNAL_TIME_INVALID) { ALOGW("invalid signal time for frame %d", (int) frame.number); return -1; } if (actualRenderTimeNs == Fence::SIGNAL_TIME_PENDING) { ALOGD("present fence has not fired for frame %d", (int) frame.number); return -1; } return actualRenderTimeNs; } void CCodecBufferChannel::pollForRenderedBuffers() { FrameEventHistoryDelta delta; mComponent->pollForRenderedFrames(&delta); processRenderedFrames(delta); } status_t CCodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) { ALOGV("[%s] discardBuffer: %p", mName, buffer.get()); bool released = false; Loading Loading @@ -1615,6 +1711,8 @@ void CCodecBufferChannel::reset() { Mutexed<Output>::Locked output(mOutput); output->buffers.reset(); } // reset the frames that are being tracked for onFrameRendered callbacks mTrackedFrames.clear(); } void CCodecBufferChannel::release() { Loading Loading @@ -1683,6 +1781,8 @@ void CCodecBufferChannel::flush(const std::list<std::unique_ptr<C2Work>> &flushe output->buffers->flushStash(); } } // reset the frames that are being tracked for onFrameRendered callbacks mTrackedFrames.clear(); } void CCodecBufferChannel::onWorkDone( Loading Loading @@ -2162,6 +2262,7 @@ status_t CCodecBufferChannel::setSurface(const sp<Surface> &newSurface, bool pus Mutexed<OutputSurface>::Locked output(mOutputSurface); output->surface = newSurface; output->generation = generation; initializeFrameTrackingFor(static_cast<ANativeWindow *>(newSurface.get())); } if (oldSurface && pushBlankBuffer) { Loading