• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 "RenderPixelCopy.h"
18 
19 #include "FormatConvert.h"
20 #include "Utils.h"
21 
22 #include <aidl/android/hardware/automotive/evs/IEvsCamera.h>
23 #include <aidl/android/hardware/automotive/evs/IEvsEnumerator.h>
24 #include <aidl/android/hardware/automotive/evs/Stream.h>
25 #include <aidlcommonsupport/NativeHandle.h>
26 #include <android-base/logging.h>
27 #include <android-base/scopeguard.h>
28 #include <android/binder_manager.h>
29 
30 namespace {
31 
32 using aidl::android::hardware::automotive::evs::BufferDesc;
33 using aidl::android::hardware::automotive::evs::IEvsCamera;
34 using aidl::android::hardware::automotive::evs::IEvsEnumerator;
35 using aidl::android::hardware::automotive::evs::Stream;
36 
37 }  // namespace
38 
RenderPixelCopy(std::shared_ptr<IEvsEnumerator> enumerator,const ConfigManager::CameraInfo & cam)39 RenderPixelCopy::RenderPixelCopy(std::shared_ptr<IEvsEnumerator> enumerator,
40                                  const ConfigManager::CameraInfo& cam) {
41     mEnumerator = enumerator;
42     mCameraInfo = cam;
43 }
44 
activate()45 bool RenderPixelCopy::activate() {
46     // Set up the camera to feed this texture
47     Stream emptyConfig;
48     std::shared_ptr<IEvsCamera> pCamera;
49     if (auto status = mEnumerator->openCamera(mCameraInfo.cameraId.c_str(), emptyConfig, &pCamera);
50         !status.isOk()) {
51         LOG(ERROR) << "Failed to allocate new EVS Camera interface";
52         return false;
53     }
54 
55     // Initialize the stream that will help us update this texture's contents
56     std::shared_ptr<StreamHandler> pStreamHandler =
57             ndk::SharedRefBase::make<StreamHandler>(pCamera);
58     if (!pStreamHandler) {
59         LOG(ERROR) << "Failed to allocate FrameHandler";
60         return false;
61     }
62 
63     // Start the video stream
64     if (!pStreamHandler->startStream()) {
65         LOG(ERROR) << "Start stream failed";
66         return false;
67     }
68 
69     mStreamHandler = pStreamHandler;
70     return true;
71 }
72 
deactivate()73 void RenderPixelCopy::deactivate() {
74     mStreamHandler.reset();
75 }
76 
drawFrame(const BufferDesc & tgtBuffer)77 bool RenderPixelCopy::drawFrame(const BufferDesc& tgtBuffer) {
78     bool success = true;
79     native_handle_t* targetBufferNativeHandle = getNativeHandle(tgtBuffer);
80     if (targetBufferNativeHandle == nullptr) {
81         LOG(ERROR) << "Target buffer has an invalid native handle.";
82         return false;
83     }
84 
85     const auto handleGuard = android::base::make_scope_guard(
86             [targetBufferNativeHandle] { free(targetBufferNativeHandle); });
87     const AHardwareBuffer_Desc* pTgtDesc =
88             reinterpret_cast<const AHardwareBuffer_Desc*>(&tgtBuffer.buffer.description);
89     android::sp<android::GraphicBuffer> tgt =
90             new android::GraphicBuffer(targetBufferNativeHandle,
91                                        android::GraphicBuffer::CLONE_HANDLE, pTgtDesc->width,
92                                        pTgtDesc->height, pTgtDesc->format, pTgtDesc->layers,
93                                        pTgtDesc->usage, pTgtDesc->stride);
94 
95     // Lock our target buffer for writing (should be RGBA8888 format)
96     uint32_t* tgtPixels = nullptr;
97     tgt->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)&tgtPixels);
98 
99     if (tgtPixels) {
100         if (pTgtDesc->format != HAL_PIXEL_FORMAT_RGBA_8888) {
101             // We always expect 32 bit RGB for the display output for now.  Is there a need for 565?
102             LOG(ERROR) << "Diplay buffer is always expected to be 32bit RGBA";
103             success = false;
104         } else {
105             // Make sure we have the latest frame data
106             if (mStreamHandler->newFrameAvailable()) {
107                 const BufferDesc& srcBuffer = mStreamHandler->getNewFrame();
108                 native_handle_t* srcBufferNativeHandle = getNativeHandle(srcBuffer);
109                 if (srcBufferNativeHandle == nullptr) {
110                     LOG(ERROR) << "Target buffer has an invalid native handle.";
111                     return false;
112                 }
113 
114                 const auto handleGuard = android::base::make_scope_guard(
115                         [srcBufferNativeHandle] { free(srcBufferNativeHandle); });
116                 const AHardwareBuffer_Desc* pSrcDesc =
117                         reinterpret_cast<const AHardwareBuffer_Desc*>(
118                                 &srcBuffer.buffer.description);
119 
120                 // Lock our source buffer for reading (current expectation are for this to be NV21
121                 // format)
122                 android::sp<android::GraphicBuffer> src =
123                         new android::GraphicBuffer(srcBufferNativeHandle,
124                                                    android::GraphicBuffer::CLONE_HANDLE,
125                                                    pSrcDesc->width, pSrcDesc->height,
126                                                    pSrcDesc->format, pSrcDesc->layers,
127                                                    pSrcDesc->usage, pSrcDesc->stride);
128 
129                 unsigned char* srcPixels = nullptr;
130                 src->lock(GRALLOC_USAGE_SW_READ_OFTEN, (void**)&srcPixels);
131                 if (srcPixels != nullptr) {
132                     // Make sure we don't run off the end of either buffer
133                     const unsigned width = std::min(pTgtDesc->width, pSrcDesc->width);
134                     const unsigned height = std::min(pTgtDesc->height, pSrcDesc->height);
135 
136                     if (pSrcDesc->format == HAL_PIXEL_FORMAT_YCRCB_420_SP) {  // 420SP == NV21
137                         copyNV21toRGB32(width, height, srcPixels, tgtPixels, pTgtDesc->stride);
138                     } else if (pSrcDesc->format == HAL_PIXEL_FORMAT_YV12) {  // YUV_420P == YV12
139                         copyYV12toRGB32(width, height, srcPixels, tgtPixels, pTgtDesc->stride);
140                     } else if (pSrcDesc->format == HAL_PIXEL_FORMAT_YCBCR_422_I) {  // YUYV
141                         copyYUYVtoRGB32(width, height, srcPixels, pSrcDesc->stride, tgtPixels,
142                                         pTgtDesc->stride);
143                     } else if (pSrcDesc->format == pTgtDesc->format) {  // 32bit RGBA
144                         copyMatchedInterleavedFormats(width, height, srcPixels, pSrcDesc->stride,
145                                                       tgtPixels, pTgtDesc->stride,
146                                                       tgtBuffer.pixelSizeBytes);
147                     }
148                 } else {
149                     LOG(ERROR) << "Failed to get pointer into src image data";
150                     success = false;
151                 }
152 
153                 mStreamHandler->doneWithFrame(srcBuffer);
154             }
155         }
156     } else {
157         LOG(ERROR) << "Failed to lock buffer contents for contents transfer";
158         success = false;
159     }
160 
161     if (tgtPixels) {
162         tgt->unlock();
163     }
164 
165     return success;
166 }
167