1 /*
2  * Copyright 2018 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 "Codec2-BufferTypes"
19 #include <android-base/logging.h>
20 
21 #include <codec2/common/BufferTypes.h>
22 
23 #include <C2AllocatorIon.h>
24 #include <C2AllocatorGralloc.h>
25 #include <C2BlockInternal.h>
26 #include <C2Buffer.h>
27 #include <C2Component.h>
28 #include <C2FenceFactory.h>
29 #include <C2PlatformSupport.h>
30 #include <C2Work.h>
31 
32 namespace android {
33 
34 // C2LinearBlock, vector<C2Param*>, C2Fence -> C2Buffer
CreateLinearBuffer(std::shared_ptr<C2Buffer> * buffer,const std::shared_ptr<C2LinearBlock> & block,const std::vector<C2Param * > & meta,const C2Fence & fence)35 bool CreateLinearBuffer(
36         std::shared_ptr<C2Buffer>* buffer,
37         const std::shared_ptr<C2LinearBlock>& block,
38         const std::vector<C2Param*>& meta,
39         const C2Fence& fence) {
40     // Check the block meta. It should have exactly 1 C2Info:
41     // C2Hal_RangeInfo.
42     if ((meta.size() != 1) || !meta[0]) {
43         LOG(ERROR) << "Invalid C2LinearBlock::meta.";
44         return false;
45     }
46     if (meta[0]->size() != sizeof(C2Hal_RangeInfo)) {
47         LOG(ERROR) << "Invalid range info in C2LinearBlock.";
48         return false;
49     }
50     C2Hal_RangeInfo *rangeInfo =
51             reinterpret_cast<C2Hal_RangeInfo*>(meta[0]);
52 
53     // Create C2Buffer from C2LinearBlock.
54     *buffer = C2Buffer::CreateLinearBuffer(block->share(
55             rangeInfo->offset, rangeInfo->length,
56             fence));
57     if (!(*buffer)) {
58         LOG(ERROR) << "CreateLinearBuffer failed.";
59         return false;
60     }
61     return true;
62 }
63 
64 // C2GraphicBlock, vector<C2Param*>, C2Fence -> C2Buffer
CreateGraphicBuffer(std::shared_ptr<C2Buffer> * buffer,const std::shared_ptr<C2GraphicBlock> & block,const std::vector<C2Param * > & meta,const C2Fence & fence)65 bool CreateGraphicBuffer(
66         std::shared_ptr<C2Buffer>* buffer,
67         const std::shared_ptr<C2GraphicBlock>& block,
68         const std::vector<C2Param*>& meta,
69         const C2Fence& fence) {
70     // Check the block meta. It should have exactly 1 C2Info:
71     // C2Hal_RectInfo.
72     if ((meta.size() != 1) || !meta[0]) {
73         LOG(ERROR) << "Invalid C2GraphicBlock::meta.";
74         return false;
75     }
76     if (meta[0]->size() != sizeof(C2Hal_RectInfo)) {
77         LOG(ERROR) << "Invalid rect info in C2GraphicBlock.";
78         return false;
79     }
80     C2Hal_RectInfo *rectInfo =
81             reinterpret_cast<C2Hal_RectInfo*>(meta[0]);
82 
83     // Create C2Buffer from C2GraphicBlock.
84     *buffer = C2Buffer::CreateGraphicBuffer(block->share(
85             C2Rect(rectInfo->width, rectInfo->height).
86             at(rectInfo->left, rectInfo->top),
87             fence));
88     if (!(*buffer)) {
89         LOG(ERROR) << "CreateGraphicBuffer failed.";
90         return false;
91     }
92     return true;
93 }
94 
95 namespace /* unnamed */ {
96 
97 template <typename BlockProcessor>
forEachBlock(C2FrameData & frameData,BlockProcessor process)98 void forEachBlock(C2FrameData& frameData,
99                   BlockProcessor process) {
100     for (const std::shared_ptr<C2Buffer>& buffer : frameData.buffers) {
101         if (buffer) {
102             for (const C2ConstGraphicBlock& block :
103                     buffer->data().graphicBlocks()) {
104                 process(block);
105             }
106         }
107     }
108 }
109 
110 template <typename BlockProcessor>
forEachBlock(const std::list<std::unique_ptr<C2Work>> & workList,BlockProcessor process,bool processInput,bool processOutput)111 void forEachBlock(const std::list<std::unique_ptr<C2Work>>& workList,
112                   BlockProcessor process,
113                   bool processInput, bool processOutput) {
114     for (const std::unique_ptr<C2Work>& work : workList) {
115         if (!work) {
116             continue;
117         }
118         if (processInput) {
119             forEachBlock(work->input, process);
120         }
121         if (processOutput) {
122             for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
123                 if (worklet) {
124                     forEachBlock(worklet->output,
125                                  process);
126                 }
127             }
128         }
129     }
130 }
131 
132 } // unnamed namespace
133 
BeginTransferBufferQueueBlock(const C2ConstGraphicBlock & block)134 bool BeginTransferBufferQueueBlock(const C2ConstGraphicBlock& block) {
135     std::shared_ptr<_C2BlockPoolData> data =
136             _C2BlockFactory::GetGraphicBlockPoolData(block);
137     if (data && _C2BlockFactory::GetBufferQueueData(data)) {
138         _C2BlockFactory::BeginTransferBlockToClient(data);
139         return true;
140     }
141     return false;
142 }
143 
BeginTransferBufferQueueBlocks(const std::list<std::unique_ptr<C2Work>> & workList,bool processInput,bool processOutput)144 void BeginTransferBufferQueueBlocks(
145         const std::list<std::unique_ptr<C2Work>>& workList,
146         bool processInput, bool processOutput) {
147     forEachBlock(workList, BeginTransferBufferQueueBlock,
148                  processInput, processOutput);
149 }
150 
EndTransferBufferQueueBlock(const C2ConstGraphicBlock & block,bool transfer)151 bool EndTransferBufferQueueBlock(
152         const C2ConstGraphicBlock& block,
153         bool transfer) {
154     std::shared_ptr<_C2BlockPoolData> data =
155             _C2BlockFactory::GetGraphicBlockPoolData(block);
156     if (data && _C2BlockFactory::GetBufferQueueData(data)) {
157         _C2BlockFactory::EndTransferBlockToClient(data, transfer);
158         return true;
159     }
160     return false;
161 }
162 
EndTransferBufferQueueBlocks(const std::list<std::unique_ptr<C2Work>> & workList,bool transfer,bool processInput,bool processOutput)163 void EndTransferBufferQueueBlocks(
164         const std::list<std::unique_ptr<C2Work>>& workList,
165         bool transfer,
166         bool processInput, bool processOutput) {
167     forEachBlock(workList,
168                  std::bind(EndTransferBufferQueueBlock,
169                            std::placeholders::_1, transfer),
170                  processInput, processOutput);
171 }
172 
DisplayBufferQueueBlock(const C2ConstGraphicBlock & block)173 bool DisplayBufferQueueBlock(const C2ConstGraphicBlock& block) {
174     std::shared_ptr<_C2BlockPoolData> data =
175             _C2BlockFactory::GetGraphicBlockPoolData(block);
176     if (data && _C2BlockFactory::GetBufferQueueData(data)) {
177         _C2BlockFactory::DisplayBlockToBufferQueue(data);
178         return true;
179     }
180     return false;
181 }
182 
183 }  // namespace android
184 
185