• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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