• 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 #include "VideoTex.h"
17 
18 #include "Utils.h"
19 #include "glError.h"
20 
21 #include <aidl/android/hardware/automotive/evs/IEvsCamera.h>
22 #include <aidl/android/hardware/automotive/evs/IEvsEnumerator.h>
23 #include <aidlcommonsupport/NativeHandle.h>
24 #include <android-base/logging.h>
25 #include <android-base/scopeguard.h>
26 #include <ui/GraphicBuffer.h>
27 
28 #include <alloca.h>
29 #include <fcntl.h>
30 #include <malloc.h>
31 #include <png.h>
32 #include <stdio.h>
33 #include <sys/ioctl.h>
34 #include <unistd.h>
35 
36 namespace {
37 
38 using aidl::android::hardware::automotive::evs::BufferDesc;
39 using aidl::android::hardware::automotive::evs::IEvsCamera;
40 using aidl::android::hardware::automotive::evs::IEvsEnumerator;
41 using aidl::android::hardware::automotive::evs::Stream;
42 using android::GraphicBuffer;
43 
44 }  // namespace
45 
VideoTex(std::shared_ptr<IEvsEnumerator> pEnum,std::shared_ptr<IEvsCamera> pCamera,std::shared_ptr<StreamHandler> pStreamHandler,EGLDisplay glDisplay)46 VideoTex::VideoTex(std::shared_ptr<IEvsEnumerator> pEnum, std::shared_ptr<IEvsCamera> pCamera,
47                    std::shared_ptr<StreamHandler> pStreamHandler, EGLDisplay glDisplay) :
48       TexWrapper(),
49       mEnumerator(pEnum),
50       mCamera(pCamera),
51       mStreamHandler(pStreamHandler),
52       mDisplay(glDisplay) {
53     // Nothing but initialization here...
54 }
55 
~VideoTex()56 VideoTex::~VideoTex() {
57     // Tell the stream to stop flowing
58     mStreamHandler->asyncStopStream();
59 
60     // Close the camera
61     mEnumerator->closeCamera(mCamera);
62 
63     // Drop our device texture image
64     if (mKHRimage != EGL_NO_IMAGE_KHR) {
65         eglDestroyImageKHR(mDisplay, mKHRimage);
66         mKHRimage = EGL_NO_IMAGE_KHR;
67     }
68 }
69 
70 // Return true if the texture contents are changed
refresh()71 bool VideoTex::refresh() {
72     if (!mStreamHandler->newFrameAvailable()) {
73         // No new image has been delivered, so there's nothing to do here
74         return false;
75     }
76 
77     // If we already have an image backing us, then it's time to return it
78     if (getNativeHandle(mImageBuffer) != nullptr) {
79         // Drop our device texture image
80         if (mKHRimage != EGL_NO_IMAGE_KHR) {
81             eglDestroyImageKHR(mDisplay, mKHRimage);
82             mKHRimage = EGL_NO_IMAGE_KHR;
83         }
84 
85         // Return it since we're done with it
86         mStreamHandler->doneWithFrame(mImageBuffer);
87     }
88 
89     // Get the new image we want to use as our contents
90     mImageBuffer = dupBufferDesc(mStreamHandler->getNewFrame());
91 
92     // create a GraphicBuffer from the existing handle
93     native_handle_t* nativeHandle = getNativeHandle(mImageBuffer);
94     const auto handleGuard =
95             android::base::make_scope_guard([nativeHandle] { free(nativeHandle); });
96     if (nativeHandle == nullptr) {
97         // New frame contains an invalid native handle.
98         return false;
99     }
100 
101     const AHardwareBuffer_Desc* pDesc =
102             reinterpret_cast<const AHardwareBuffer_Desc*>(&mImageBuffer.buffer.description);
103     android::sp<GraphicBuffer> pGfxBuffer =  // AHardwareBuffer_to_GraphicBuffer?
104             new GraphicBuffer(nativeHandle, GraphicBuffer::CLONE_HANDLE, pDesc->width,
105                               pDesc->height, pDesc->format, pDesc->layers, pDesc->usage,
106                               pDesc->stride);
107     if (!pGfxBuffer) {
108         LOG(ERROR) << "Failed to allocate GraphicBuffer to wrap image handle";
109         // Returning "true" in this error condition because we already released the
110         // previous image (if any) and so the texture may change in unpredictable ways now!
111         return true;
112     }
113 
114     if (auto status = pGfxBuffer->initCheck(); status != android::OK) {
115         LOG(ERROR) << "Failed to initialize the graphic buffer, error = "
116                    << android::statusToString(status);
117         // Same here.
118         return true;
119     }
120 
121     // Get a GL compatible reference to the graphics buffer we've been given
122     EGLint eglImageAttributes[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
123     EGLClientBuffer clientBuf = static_cast<EGLClientBuffer>(pGfxBuffer->getNativeBuffer());
124     mKHRimage = eglCreateImageKHR(mDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuf,
125                                   eglImageAttributes);
126     if (mKHRimage == EGL_NO_IMAGE_KHR) {
127         const char* msg = getEGLError();
128         LOG(ERROR) << "Error creating EGLImage: " << msg;
129     } else {
130         // Update the texture handle we already created to refer to this gralloc buffer
131         glActiveTexture(GL_TEXTURE0);
132         glBindTexture(GL_TEXTURE_2D, glId());
133         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, static_cast<GLeglImageOES>(mKHRimage));
134 
135         // Initialize the sampling properties (it seems the sample may not work if this isn't done)
136         // The user of this texture may very well want to set their own filtering, but we're going
137         // to pay the (minor) price of setting this up for them to avoid the dreaded "black image"
138         // if they forget.
139         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
140         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
141         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
142         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
143     }
144 
145     return true;
146 }
147 
createVideoTexture(const std::shared_ptr<IEvsEnumerator> & pEnum,const char * evsCameraId,std::unique_ptr<Stream> streamCfg,EGLDisplay glDisplay,bool useExternalMemory,android_pixel_format_t format)148 VideoTex* createVideoTexture(const std::shared_ptr<IEvsEnumerator>& pEnum, const char* evsCameraId,
149                              std::unique_ptr<Stream> streamCfg, EGLDisplay glDisplay,
150                              bool useExternalMemory, android_pixel_format_t format) {
151     // Set up the camera to feed this texture
152     std::shared_ptr<IEvsCamera> pCamera;
153     std::shared_ptr<StreamHandler> pStreamHandler;
154     if (!streamCfg) {
155         LOG(ERROR) << "Given stream configuration is invalid.";
156         return nullptr;
157     }
158 
159     if (auto status = pEnum->openCamera(evsCameraId, *streamCfg, &pCamera); !status.isOk()) {
160         LOG(ERROR) << "Failed to open a camera " << evsCameraId;
161         return nullptr;
162     }
163 
164     // Initialize the stream that will help us update this texture's contents
165     pStreamHandler =
166             ndk::SharedRefBase::make<StreamHandler>(pCamera, /* numBuffers= */ 2, useExternalMemory,
167                                                     format, streamCfg->width, streamCfg->height);
168     if (!pStreamHandler) {
169         LOG(ERROR) << "Failed to allocate FrameHandler";
170         return nullptr;
171     }
172 
173     // Start the video stream
174     if (!pStreamHandler->startStream()) {
175         printf("Couldn't start the camera stream (%s)\n", evsCameraId);
176         LOG(ERROR) << "Start stream failed for " << evsCameraId;
177         return nullptr;
178     }
179 
180     return new VideoTex(pEnum, pCamera, pStreamHandler, glDisplay);
181 }
182