1 /*
2 * Copyright (C) 2019 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_NDEBUG 0
18 #define LOG_TAG "FrameCaptureProcessor"
19
20 #include <media/stagefright/foundation/ADebug.h>
21 #include <media/stagefright/foundation/AMessage.h>
22 #include <media/stagefright/FrameCaptureProcessor.h>
23 #include <media/stagefright/MediaErrors.h>
24 #include <renderengine/RenderEngine.h>
25 #include <ui/Fence.h>
26 #include <ui/PixelFormat.h>
27 #include <utils/Log.h>
28
29 namespace android {
30
31 //static
32 Mutex FrameCaptureProcessor::sLock;
33 //static
34 sp<FrameCaptureProcessor> FrameCaptureProcessor::sInstance;
35
36 //static
getInstance()37 sp<FrameCaptureProcessor> FrameCaptureProcessor::getInstance() {
38 Mutex::Autolock _l(sLock);
39 if (sInstance == nullptr) {
40 sInstance = new FrameCaptureProcessor();
41 sInstance->createRenderEngine();
42 }
43 // init only once, if failed nullptr will be returned afterwards.
44 return (sInstance->initCheck() == OK) ? sInstance : nullptr;
45 }
46
47 //static
PostAndAwaitResponse(const sp<AMessage> & msg,sp<AMessage> * response)48 status_t FrameCaptureProcessor::PostAndAwaitResponse(
49 const sp<AMessage> &msg, sp<AMessage> *response) {
50 status_t err = msg->postAndAwaitResponse(response);
51
52 if (err != OK) {
53 return err;
54 }
55
56 if (!(*response)->findInt32("err", &err)) {
57 err = OK;
58 }
59
60 return err;
61 }
62
63 //static
PostReplyWithError(const sp<AReplyToken> & replyID,status_t err)64 void FrameCaptureProcessor::PostReplyWithError(
65 const sp<AReplyToken> &replyID, status_t err) {
66 sp<AMessage> response = new AMessage;
67 if (err != OK) {
68 response->setInt32("err", err);
69 }
70 response->postReply(replyID);
71 }
72
FrameCaptureProcessor()73 FrameCaptureProcessor::FrameCaptureProcessor()
74 : mInitStatus(NO_INIT), mTextureName(0) {}
75
~FrameCaptureProcessor()76 FrameCaptureProcessor::~FrameCaptureProcessor() {
77 if (mLooper != nullptr) {
78 mLooper->unregisterHandler(id());
79 mLooper->stop();
80 }
81 }
82
createRenderEngine()83 void FrameCaptureProcessor::createRenderEngine() {
84 // this method should only be called once, immediately after ctor
85 CHECK(mInitStatus == NO_INIT);
86
87 mLooper = new ALooper();
88 mLooper->setName("capture_looper");
89 mLooper->start(); // default priority
90 mLooper->registerHandler(this);
91
92 sp<AMessage> response;
93 status_t err = PostAndAwaitResponse(new AMessage(kWhatCreate, this), &response);
94 if (err != OK) {
95 mInitStatus = ERROR_UNSUPPORTED;
96
97 mLooper->unregisterHandler(id());
98 mLooper->stop();
99 mLooper.clear();
100 return;
101 }
102
103 // only need one texture name
104 mRE->genTextures(1, &mTextureName);
105
106 mInitStatus = OK;
107 }
108
capture(const sp<Layer> & layer,const Rect & sourceCrop,const sp<GraphicBuffer> & buffer)109 status_t FrameCaptureProcessor::capture(
110 const sp<Layer> &layer, const Rect &sourceCrop, const sp<GraphicBuffer> &buffer) {
111 sp<AMessage> msg = new AMessage(kWhatCapture, this);
112 msg->setObject("layer", layer);
113 msg->setRect("crop", sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom);
114 msg->setObject("buffer", buffer);
115 sp<AMessage> response;
116 return PostAndAwaitResponse(msg, &response);
117 }
118
onCreate()119 status_t FrameCaptureProcessor::onCreate() {
120 mRE = renderengine::RenderEngine::create(
121 renderengine::RenderEngineCreationArgs::Builder()
122 .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
123 .setImageCacheSize(2 /*maxFrameBufferAcquiredBuffers*/)
124 .setUseColorManagerment(true)
125 .setEnableProtectedContext(false)
126 .setPrecacheToneMapperShaderOnly(true)
127 .setContextPriority(renderengine::RenderEngine::ContextPriority::LOW)
128 .build());
129
130 if (mRE == nullptr) {
131 return ERROR_UNSUPPORTED;
132 }
133 return OK;
134 }
135
onCapture(const sp<Layer> & layer,const Rect & sourceCrop,const sp<GraphicBuffer> & buffer)136 status_t FrameCaptureProcessor::onCapture(const sp<Layer> &layer,
137 const Rect &sourceCrop, const sp<GraphicBuffer> &buffer) {
138 renderengine::DisplaySettings clientCompositionDisplay;
139 std::vector<const renderengine::LayerSettings*> clientCompositionLayers;
140
141 clientCompositionDisplay.physicalDisplay = sourceCrop;
142 clientCompositionDisplay.clip = sourceCrop;
143
144 clientCompositionDisplay.outputDataspace = ui::Dataspace::V0_SRGB;
145 clientCompositionDisplay.maxLuminance = sDefaultMaxLumiance;
146 clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
147
148 // from Layer && BufferLayer
149 renderengine::LayerSettings layerSettings;
150
151 layer->getLayerSettings(sourceCrop, mTextureName, &layerSettings);
152
153 clientCompositionLayers.push_back(&layerSettings);
154
155 // Use an empty fence for the buffer fence, since we just created the buffer so
156 // there is no need for synchronization with the GPU.
157 base::unique_fd bufferFence;
158 base::unique_fd drawFence;
159 mRE->useProtectedContext(false);
160 status_t err = mRE->drawLayers(clientCompositionDisplay, clientCompositionLayers, buffer.get(),
161 /*useFramebufferCache=*/false, std::move(bufferFence), &drawFence);
162
163 sp<Fence> fence = new Fence(std::move(drawFence));
164
165 if (err != OK) {
166 ALOGE("drawLayers returned err %d", err);
167 } else {
168 err = fence->wait(500);
169 if (err != OK) {
170 ALOGW("wait for fence returned err %d", err);
171 err = OK;
172 }
173 }
174 mRE->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL);
175 return err;
176 }
177
onMessageReceived(const sp<AMessage> & msg)178 void FrameCaptureProcessor::onMessageReceived(const sp<AMessage> &msg) {
179 switch (msg->what()) {
180 case kWhatCreate:
181 {
182 sp<AReplyToken> replyID;
183 CHECK(msg->senderAwaitsResponse(&replyID));
184
185 status_t err = onCreate();
186
187 PostReplyWithError(replyID, err);
188 break;
189 }
190 case kWhatCapture:
191 {
192 sp<AReplyToken> replyID;
193 CHECK(msg->senderAwaitsResponse(&replyID));
194
195 sp<RefBase> layerObj, bufferObj;
196 int32_t left, top, right, bottom;
197 CHECK(msg->findObject("layer", &layerObj));
198 CHECK(msg->findRect("crop", &left, &top, &right, &bottom));
199 CHECK(msg->findObject("buffer", &bufferObj));
200
201 sp<GraphicBuffer> buffer = static_cast<GraphicBuffer*>(bufferObj.get());
202 sp<Layer> layer = static_cast<Layer*>(layerObj.get());
203
204 PostReplyWithError(replyID,
205 onCapture(layer, Rect(left, top, right, bottom), buffer));
206
207 break;
208 }
209 default:
210 TRESPASS();
211 }
212 }
213
214 } // namespace android
215