xref: /aosp_15_r20/frameworks/av/media/codec2/vndk/platform/C2BqPoolInvalidator.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "C2BqPoolInvalidator"
19 #include <utils/Log.h>
20 #include <utils/SystemClock.h>
21 
22 #include <C2BqBufferPriv.h>
23 #include <C2BqPoolInvalidator.h>
24 
25 namespace android {
26 
27 namespace {
28     static constexpr int64_t kBqPoolInvalidateDelayMs = 1000;
29 } // anonymous namespace
30 
C2BqPoolInvalidateItem(std::list<std::shared_ptr<C2BufferQueueBlockPool>> && pools)31 C2BqPoolInvalidateItem::C2BqPoolInvalidateItem(
32         std::list<std::shared_ptr<C2BufferQueueBlockPool>> &&pools) : mPools(std::move(pools)) {
33     if (!mPools.empty()) {
34         mNeedsInvalidate = true;
35     } else {
36         mNeedsInvalidate = false;
37     }
38 }
39 
invalidate()40 void C2BqPoolInvalidateItem::invalidate() {
41     std::list<std::shared_ptr<C2BufferQueueBlockPool>> pools;
42     {
43         std::unique_lock<std::mutex> l(mLock);
44         if (!mNeedsInvalidate) {
45             return;
46         }
47         pools = std::move(mPools);
48         mNeedsInvalidate = false;
49     }
50     for(auto it = pools.begin(); it != pools.end(); ++it) {
51         (*it)->invalidate();
52     }
53 }
54 
skip()55 void C2BqPoolInvalidateItem::skip() {
56     std::unique_lock<std::mutex> l(mLock);
57     mNeedsInvalidate = false;
58     mPools.clear();
59 }
60 
needsInvalidate()61 bool C2BqPoolInvalidateItem::needsInvalidate() {
62     std::unique_lock<std::mutex> l(mLock);
63     return mNeedsInvalidate;
64 }
65 
getInstance()66 C2BqPoolInvalidator &C2BqPoolInvalidator::getInstance() {
67     static android::base::NoDestructor<C2BqPoolInvalidator> sInvalidator;
68     return *sInvalidator;
69 }
70 
C2BqPoolInvalidator()71 C2BqPoolInvalidator::C2BqPoolInvalidator() : mDone(false) {
72     mThread = std::thread(&C2BqPoolInvalidator::run, this);
73 }
74 
~C2BqPoolInvalidator()75 C2BqPoolInvalidator::~C2BqPoolInvalidator() {
76     {
77         std::unique_lock<std::mutex> l(mMutex);
78         mDone = true;
79         mCv.notify_one();
80     }
81     if (mThread.joinable()) {
82         mThread.join();
83     }
84 }
85 
queue(std::shared_ptr<C2BqPoolInvalidateItem> & item)86 void C2BqPoolInvalidator::queue(std::shared_ptr<C2BqPoolInvalidateItem> &item) {
87     std::unique_lock<std::mutex> l(mMutex);
88     std::pair<int64_t, std::shared_ptr<C2BqPoolInvalidateItem>> p =
89             std::make_pair(::android::elapsedRealtime() + kBqPoolInvalidateDelayMs, item);
90     mItems.push_back(p);
91     mCv.notify_one();
92 }
93 
run()94 void C2BqPoolInvalidator::run() {
95     while(true) {
96         int64_t nowMs = ::android::elapsedRealtime();
97         std::unique_lock<std::mutex> l(mMutex);
98         if (mDone) {
99             break;
100         }
101         std::list<std::shared_ptr<C2BqPoolInvalidateItem>> items;
102         while (!mItems.empty()) {
103             if (mItems.front().first <= nowMs) {
104                 items.push_back(mItems.front().second);
105                 mItems.pop_front();
106             } else {
107                 break;
108             }
109         }
110         if (items.empty()) {
111             if (mItems.empty()) {
112                 mCv.wait(l);
113             } else {
114                 int64_t nextMs = mItems.front().first;
115                 if (nextMs > nowMs) {
116                     mCv.wait_for(l, std::chrono::milliseconds(nextMs - nowMs));
117                 }
118             }
119         } else {
120             l.unlock();
121             int invalidated = 0;
122             for (auto it = items.begin(); it != items.end(); ++it, ++invalidated) {
123                 (*it)->invalidate();
124             }
125             ALOGD("invalidated %d bqpool items", invalidated);
126         }
127     }
128 }
129 
130 } // android
131