Home | History | Annotate | Download | only in manager
      1 /*
      2  * Copyright (C) 2016 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 #include "HalCamera.h"
     18 #include "VirtualCamera.h"
     19 #include "Enumerator.h"
     20 
     21 #include <ui/GraphicBufferAllocator.h>
     22 #include <ui/GraphicBufferMapper.h>
     23 
     24 
     25 namespace android {
     26 namespace automotive {
     27 namespace evs {
     28 namespace V1_0 {
     29 namespace implementation {
     30 
     31 
     32 // TODO:  We need to hook up death monitoring to detect stream death so we can attempt a reconnect
     33 
     34 
     35 sp<VirtualCamera> HalCamera::makeVirtualCamera() {
     36 
     37     // Create the client camera interface object
     38     sp<VirtualCamera> client = new VirtualCamera(this);
     39     if (client == nullptr) {
     40         ALOGE("Failed to create client camera object");
     41         return nullptr;
     42     }
     43 
     44     // Make sure we have enough buffers available for all our clients
     45     if (!changeFramesInFlight(client->getAllowedBuffers())) {
     46         // Gah!  We couldn't get enough buffers, so we can't support this client
     47         // Null the pointer, dropping our reference, thus destroying the client object
     48         client = nullptr;
     49         return nullptr;
     50     }
     51 
     52     // Add this client to our ownership list via weak pointer
     53     mClients.push_back(client);
     54 
     55     // Return the strong pointer to the client
     56     return client;
     57 }
     58 
     59 
     60 void HalCamera::disownVirtualCamera(sp<VirtualCamera> virtualCamera) {
     61     // Ignore calls with null pointers
     62     if (virtualCamera.get() == nullptr) {
     63         ALOGW("Ignoring disownVirtualCamera call with null pointer");
     64         return;
     65     }
     66 
     67     // Make sure the virtual camera's stream is stopped
     68     virtualCamera->stopVideoStream();
     69 
     70     // Remove the virtual camera from our client list
     71     unsigned clientCount = mClients.size();
     72     mClients.remove(virtualCamera);
     73     if (clientCount != mClients.size() + 1) {
     74         ALOGE("Couldn't find camera in our client list to remove it");
     75     }
     76     virtualCamera->shutdown();
     77 
     78     // Recompute the number of buffers required with the target camera removed from the list
     79     if (!changeFramesInFlight(0)) {
     80         ALOGE("Error when trying to reduce the in flight buffer count");
     81     }
     82 }
     83 
     84 
     85 bool HalCamera::changeFramesInFlight(int delta) {
     86     // Walk all our clients and count their currently required frames
     87     unsigned bufferCount = 0;
     88     for (auto&& client :  mClients) {
     89         sp<VirtualCamera> virtCam = client.promote();
     90         if (virtCam != nullptr) {
     91             bufferCount += virtCam->getAllowedBuffers();
     92         }
     93     }
     94 
     95     // Add the requested delta
     96     bufferCount += delta;
     97 
     98     // Never drop below 1 buffer -- even if all client cameras get closed
     99     if (bufferCount < 1) {
    100         bufferCount = 1;
    101     }
    102 
    103     // Ask the hardware for the resulting buffer count
    104     Return<EvsResult> result = mHwCamera->setMaxFramesInFlight(bufferCount);
    105     bool success = (result.isOk() && result == EvsResult::OK);
    106 
    107     // Update the size of our array of outstanding frame records
    108     if (success) {
    109         std::vector<FrameRecord> newRecords;
    110         newRecords.reserve(bufferCount);
    111 
    112         // Copy and compact the old records that are still active
    113         for (const auto& rec : mFrames) {
    114             if (rec.refCount > 0) {
    115                 newRecords.emplace_back(rec);
    116             }
    117         }
    118         if (newRecords.size() > (unsigned)bufferCount) {
    119             ALOGW("We found more frames in use than requested.");
    120         }
    121 
    122         mFrames.swap(newRecords);
    123     }
    124 
    125     return success;
    126 }
    127 
    128 
    129 Return<EvsResult> HalCamera::clientStreamStarting() {
    130     Return<EvsResult> result = EvsResult::OK;
    131 
    132     if (mStreamState == STOPPED) {
    133         result = mHwCamera->startVideoStream(this);
    134     }
    135 
    136     return result;
    137 }
    138 
    139 
    140 void HalCamera::clientStreamEnding() {
    141     // Do we still have a running client?
    142     bool stillRunning = false;
    143     for (auto&& client : mClients) {
    144         sp<VirtualCamera> virtCam = client.promote();
    145         if (virtCam != nullptr) {
    146             stillRunning |= virtCam->isStreaming();
    147         }
    148     }
    149 
    150     // If not, then stop the hardware stream
    151     if (!stillRunning) {
    152         mHwCamera->stopVideoStream();
    153     }
    154 }
    155 
    156 
    157 Return<void> HalCamera::doneWithFrame(const BufferDesc& buffer) {
    158     // Find this frame in our list of outstanding frames
    159     unsigned i;
    160     for (i=0; i<mFrames.size(); i++) {
    161         if (mFrames[i].frameId == buffer.bufferId) {
    162             break;
    163         }
    164     }
    165     if (i == mFrames.size()) {
    166         ALOGE("We got a frame back with an ID we don't recognize!");
    167     } else {
    168         // Are there still clients using this buffer?
    169         mFrames[i].refCount--;
    170         if (mFrames[i].refCount <= 0) {
    171             // Since all our clients are done with this buffer, return it to the device layer
    172             mHwCamera->doneWithFrame(buffer);
    173         }
    174     }
    175 
    176     return Void();
    177 }
    178 
    179 
    180 Return<void> HalCamera::deliverFrame(const BufferDesc& buffer) {
    181     // Run through all our clients and deliver this frame to any who are eligible
    182     unsigned frameDeliveries = 0;
    183     for (auto&& client : mClients) {
    184         sp<VirtualCamera> virtCam = client.promote();
    185         if (virtCam != nullptr) {
    186             if (virtCam->deliverFrame(buffer)) {
    187                 frameDeliveries++;
    188             }
    189         }
    190     }
    191 
    192     if (frameDeliveries < 1) {
    193         // If none of our clients could accept the frame, then return it right away
    194         ALOGI("Trivially rejecting frame with no acceptances");
    195         mHwCamera->doneWithFrame(buffer);
    196     } else {
    197         // Add an entry for this frame in our tracking list
    198         unsigned i;
    199         for (i=0; i<mFrames.size(); i++) {
    200             if (mFrames[i].refCount == 0) {
    201                 break;
    202             }
    203         }
    204         if (i == mFrames.size()) {
    205             mFrames.emplace_back(buffer.bufferId);
    206         } else {
    207             mFrames[i].frameId = buffer.bufferId;
    208         }
    209         mFrames[i].refCount = frameDeliveries;
    210     }
    211 
    212     return Void();
    213 }
    214 
    215 } // namespace implementation
    216 } // namespace V1_0
    217 } // namespace evs
    218 } // namespace automotive
    219 } // namespace android
    220