xref: /aosp_15_r20/frameworks/av/services/camera/libcameraservice/common/FrameProcessorBase.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2013 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_TAG "Camera2-FrameProcessorBase"
18 #define ATRACE_TAG ATRACE_TAG_CAMERA
19 //#define LOG_NDEBUG 0
20 
21 #include <map>
22 #include <utils/Log.h>
23 #include <utils/Trace.h>
24 #include <camera/StringUtils.h>
25 
26 #include "common/FrameProducer.h"
27 #include "common/FrameProcessorBase.h"
28 
29 namespace android {
30 namespace camera2 {
31 
32 using CameraMetadataInfo = android::hardware::camera2::CameraMetadataInfo;
33 
FrameProcessorBase(wp<FrameProducer> device)34 FrameProcessorBase::FrameProcessorBase(wp<FrameProducer> device) :
35     Thread(/*canCallJava*/false),
36     mDevice(device),
37     mNumPartialResults(1) {
38     sp<FrameProducer> cameraDevice = device.promote();
39     if (cameraDevice != 0) {
40         CameraMetadata staticInfo = cameraDevice->info();
41         camera_metadata_entry_t entry = staticInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
42         if (entry.count > 0) {
43             mNumPartialResults = entry.data.i32[0];
44         }
45     }
46 }
47 
~FrameProcessorBase()48 FrameProcessorBase::~FrameProcessorBase() {
49     ALOGV("%s: Exit", __FUNCTION__);
50 }
51 
registerListener(int32_t minId,int32_t maxId,const wp<FilteredListener> & listener,bool sendPartials)52 status_t FrameProcessorBase::registerListener(int32_t minId,
53         int32_t maxId, const wp<FilteredListener>& listener, bool sendPartials) {
54     Mutex::Autolock l(mInputMutex);
55     List<RangeListener>::iterator item = mRangeListeners.begin();
56     while (item != mRangeListeners.end()) {
57         if (item->minId == minId &&
58                 item->maxId == maxId &&
59                 item->listener == listener) {
60             // already registered, just return
61             ALOGV("%s: Attempt to register the same client twice, ignoring",
62                     __FUNCTION__);
63             return OK;
64         }
65         item++;
66     }
67     ALOGV("%s: Registering listener for frame id range %d - %d",
68             __FUNCTION__, minId, maxId);
69     RangeListener rListener = { minId, maxId, listener, sendPartials };
70     mRangeListeners.push_back(rListener);
71     return OK;
72 }
73 
removeListener(int32_t minId,int32_t maxId,const wp<FilteredListener> & listener)74 status_t FrameProcessorBase::removeListener(int32_t minId,
75                                            int32_t maxId,
76                                            const wp<FilteredListener>& listener) {
77     Mutex::Autolock l(mInputMutex);
78     List<RangeListener>::iterator item = mRangeListeners.begin();
79     while (item != mRangeListeners.end()) {
80         if (item->minId == minId &&
81                 item->maxId == maxId &&
82                 item->listener == listener) {
83             item = mRangeListeners.erase(item);
84         } else {
85             item++;
86         }
87     }
88     return OK;
89 }
90 
dump(int fd,const Vector<String16> &)91 void FrameProcessorBase::dump(int fd, const Vector<String16>& /*args*/) {
92     std::string result("    Latest received frame:\n");
93     write(fd, result.c_str(), result.size());
94 
95     CameraMetadata lastFrame;
96     std::map<std::string, CameraMetadata> lastPhysicalFrames;
97     {
98         // Don't race while dumping metadata
99         Mutex::Autolock al(mLastFrameMutex);
100         lastFrame = CameraMetadata(mLastFrame);
101 
102         for (const auto& physicalFrame : mLastPhysicalFrames) {
103             lastPhysicalFrames.emplace(physicalFrame.mPhysicalCameraId,
104                     physicalFrame.mCameraMetadataInfo.get<CameraMetadataInfo::metadata>());
105         }
106     }
107     lastFrame.dump(fd, /*verbosity*/2, /*indentation*/6);
108 
109     for (const auto& physicalFrame : lastPhysicalFrames) {
110         result = fmt::sprintf("   Latest received frame for physical camera %s:\n",
111                 physicalFrame.first.c_str());
112         write(fd, result.c_str(), result.size());
113         CameraMetadata lastPhysicalMetadata = CameraMetadata(physicalFrame.second);
114         lastPhysicalMetadata.sort();
115         lastPhysicalMetadata.dump(fd, /*verbosity*/2, /*indentation*/6);
116     }
117 }
118 
threadLoop()119 bool FrameProcessorBase::threadLoop() {
120     status_t res;
121 
122     sp<FrameProducer> device;
123     {
124         device = mDevice.promote();
125         if (device == 0) return false;
126     }
127 
128     res = device->waitForNextFrame(kWaitDuration);
129     if (res == OK) {
130         processNewFrames(device);
131     } else if (res != TIMED_OUT) {
132         ALOGE("FrameProcessorBase: Error waiting for new "
133                 "frames: %s (%d)", strerror(-res), res);
134     }
135 
136     return true;
137 }
138 
processNewFrames(const sp<FrameProducer> & device)139 void FrameProcessorBase::processNewFrames(const sp<FrameProducer> &device) {
140     status_t res;
141     ATRACE_CALL();
142     CaptureResult result;
143 
144     ALOGV("%s: Camera %s: Process new frames", __FUNCTION__, device->getId().c_str());
145 
146     while ( (res = device->getNextResult(&result)) == OK) {
147 
148         // TODO: instead of getting frame number from metadata, we should read
149         // this from result.mResultExtras when FrameProducer interface is fixed.
150         camera_metadata_entry_t entry;
151 
152         entry = result.mMetadata.find(ANDROID_REQUEST_FRAME_COUNT);
153         if (entry.count == 0) {
154             ALOGE("%s: Camera %s: Error reading frame number",
155                     __FUNCTION__, device->getId().c_str());
156             break;
157         }
158         ATRACE_INT("cam2_frame", entry.data.i32[0]);
159 
160         if (!processSingleFrame(result, device)) {
161             break;
162         }
163 
164         if (!result.mMetadata.isEmpty()) {
165             Mutex::Autolock al(mLastFrameMutex);
166             mLastFrame.acquire(result.mMetadata);
167 
168             mLastPhysicalFrames = std::move(result.mPhysicalMetadatas);
169         }
170     }
171     if (res != NOT_ENOUGH_DATA) {
172         ALOGE("%s: Camera %s: Error getting next frame: %s (%d)",
173                 __FUNCTION__, device->getId().c_str(), strerror(-res), res);
174         return;
175     }
176 
177     return;
178 }
179 
processSingleFrame(CaptureResult & result,const sp<FrameProducer> & device)180 bool FrameProcessorBase::processSingleFrame(CaptureResult &result,
181                                             const sp<FrameProducer> &device) {
182     ALOGV("%s: Camera %s: Process single frame (is empty? %d)",
183             __FUNCTION__, device->getId().c_str(), result.mMetadata.isEmpty());
184     return processListeners(result, device) == OK;
185 }
186 
processListeners(const CaptureResult & result,const sp<FrameProducer> & device)187 status_t FrameProcessorBase::processListeners(const CaptureResult &result,
188         const sp<FrameProducer> &device) {
189     ATRACE_CALL();
190 
191     camera_metadata_ro_entry_t entry;
192 
193     // Check if this result is partial.
194     bool isPartialResult =
195             result.mResultExtras.partialResultCount < mNumPartialResults;
196 
197     // TODO: instead of getting requestID from CameraMetadata, we should get it
198     // from CaptureResultExtras. This will require changing Camera2Device.
199     // Currently Camera2Device uses MetadataQueue to store results, which does not
200     // include CaptureResultExtras.
201     entry = result.mMetadata.find(ANDROID_REQUEST_ID);
202     if (entry.count == 0) {
203         ALOGE("%s: Camera %s: Error reading frame id", __FUNCTION__, device->getId().c_str());
204         return BAD_VALUE;
205     }
206     int32_t requestId = entry.data.i32[0];
207 
208     List<sp<FilteredListener> > listeners;
209     {
210         Mutex::Autolock l(mInputMutex);
211 
212         List<RangeListener>::iterator item = mRangeListeners.begin();
213         // Don't deliver partial results to listeners that don't want them
214         while (item != mRangeListeners.end()) {
215             if (requestId >= item->minId && requestId < item->maxId &&
216                     (!isPartialResult || item->sendPartials)) {
217                 sp<FilteredListener> listener = item->listener.promote();
218                 if (listener == 0) {
219                     item = mRangeListeners.erase(item);
220                     continue;
221                 } else {
222                     listeners.push_back(listener);
223                 }
224             }
225             item++;
226         }
227     }
228     ALOGV("%s: Camera %s: Got %zu range listeners out of %zu", __FUNCTION__,
229           device->getId().c_str(), listeners.size(), mRangeListeners.size());
230 
231     List<sp<FilteredListener> >::iterator item = listeners.begin();
232     for (; item != listeners.end(); item++) {
233         (*item)->onResultAvailable(result);
234     }
235     return OK;
236 }
237 
238 }; // namespace camera2
239 }; // namespace android
240