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