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