1 /*
2  * Copyright 2020 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_TAG "SampleFilterPlugin"
18 #include <android-base/logging.h>
19 
20 #include <chrono>
21 #include <thread>
22 
23 #include <codec2/hidl/plugin/FilterPlugin.h>
24 
25 #include <C2AllocatorGralloc.h>
26 #include <C2Config.h>
27 #include <C2PlatformSupport.h>
28 #include <Codec2Mapper.h>
29 #include <util/C2InterfaceHelper.h>
30 
31 #include <renderengine/RenderEngine.h>
32 #include <system/window.h>
33 #include <ui/GraphicBuffer.h>
34 #include <utils/RefBase.h>
35 
36 typedef C2StreamParam<C2Info, C2ColorAspectsStruct,
37                 kParamIndexColorAspects | C2Param::CoreIndex::IS_REQUEST_FLAG>
38         C2StreamColorAspectsRequestInfo;
39 
40 // In practice the vendor parameters will be defined in a separate header file,
41 // but for the purpose of this sample, we just define it here.
42 
43 // Vendor-specific type index for filters start from this value. 0x7000 is added to
44 // avoid conflict with existing vendor type indices.
45 constexpr uint32_t kTypeIndexFilterStart = C2Param::TYPE_INDEX_VENDOR_START + 0x7000;
46 // Answer to the Ultimate Question of Life, the Universe, and Everything
47 // (Reference to The Hitchhiker's Guide to the Galaxy by Douglas Adams)
48 constexpr uint32_t kParamIndexVendorUltimateAnswer = kTypeIndexFilterStart + 0;
49 typedef C2StreamParam<C2Info, C2Int32Value, kParamIndexVendorUltimateAnswer>
50         C2StreamVendorUltimateAnswerInfo;
51 constexpr char C2_PARAMKEY_VENDOR_ULTIMATE_ANSWER[] = "ultimate-answer";
52 
53 namespace android {
54 
55 using namespace std::literals::chrono_literals;
56 
57 class SampleToneMappingFilter
58     : public C2Component, public std::enable_shared_from_this<SampleToneMappingFilter> {
59 public:
60     class Interface : public C2ComponentInterface {
61     public:
62         static const std::string NAME;
63         static const FilterPlugin_V1::Descriptor DESCRIPTOR;
64 
Interface(c2_node_id_t id,const std::shared_ptr<C2ReflectorHelper> & reflector)65         Interface(c2_node_id_t id, const std::shared_ptr<C2ReflectorHelper> &reflector)
66             : mId(id),
67               mHelper(reflector) {
68         }
69         ~Interface() override = default;
getName() const70         C2String getName() const override { return NAME; }
getId() const71         c2_node_id_t getId() const override { return mId; }
72 
query_vb(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2Param>> * const heapParams) const73         c2_status_t query_vb(
74                 const std::vector<C2Param*> &stackParams,
75                 const std::vector<C2Param::Index> &heapParamIndices,
76                 c2_blocking_t mayBlock,
77                 std::vector<std::unique_ptr<C2Param>>* const heapParams) const override {
78             return mHelper.query(stackParams, heapParamIndices, mayBlock, heapParams);
79         }
config_vb(const std::vector<C2Param * > & params,c2_blocking_t mayBlock,std::vector<std::unique_ptr<C2SettingResult>> * const failures)80         c2_status_t config_vb(
81                 const std::vector<C2Param*> &params,
82                 c2_blocking_t mayBlock,
83                 std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
84             return mHelper.config(params, mayBlock, failures);
85         }
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const86         c2_status_t querySupportedParams_nb(
87                 std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override {
88             return mHelper.querySupportedParams(params);
89         }
querySupportedValues_vb(std::vector<C2FieldSupportedValuesQuery> & fields,c2_blocking_t mayBlock) const90         c2_status_t querySupportedValues_vb(
91                 std::vector<C2FieldSupportedValuesQuery> &fields,
92                 c2_blocking_t mayBlock) const override {
93             return mHelper.querySupportedValues(fields, mayBlock);
94         }
createTunnel_sm(c2_node_id_t)95         c2_status_t createTunnel_sm(c2_node_id_t) override { return C2_OMITTED; }
releaseTunnel_sm(c2_node_id_t)96         c2_status_t releaseTunnel_sm(c2_node_id_t) override { return C2_OMITTED; }
97 
getDataSpace()98         uint32_t getDataSpace() {
99             Helper::Lock lock = mHelper.lock();
100             uint32_t dataspace = HAL_DATASPACE_UNKNOWN;
101             C2Mapper::map(
102                     mHelper.mInputColorAspectInfo->range,
103                     mHelper.mInputColorAspectInfo->primaries,
104                     mHelper.mInputColorAspectInfo->matrix,
105                     mHelper.mInputColorAspectInfo->transfer,
106                     &dataspace);
107             return dataspace;
108         }
getHdrStaticMetadata()109         std::shared_ptr<C2StreamHdrStaticInfo::input> getHdrStaticMetadata() {
110             Helper::Lock lock = mHelper.lock();
111             return mHelper.mInputHdrStaticInfo;
112         }
getPoolId()113         C2BlockPool::local_id_t getPoolId() {
114             Helper::Lock lock = mHelper.lock();
115             return mHelper.mOutputPoolIds->m.values[0];
116         }
117 
IsFilteringEnabled(const std::shared_ptr<C2ComponentInterface> & intf)118         static bool IsFilteringEnabled(const std::shared_ptr<C2ComponentInterface> &intf) {
119             C2StreamColorAspectsRequestInfo::output info(0u);
120             std::vector<std::unique_ptr<C2Param>> heapParams;
121             c2_status_t err = intf->query_vb({&info}, {}, C2_MAY_BLOCK, &heapParams);
122             if (err != C2_OK && err != C2_BAD_INDEX) {
123                 LOG(WARNING) << "SampleToneMappingFilter::Interface::IsFilteringEnabled: "
124                         << "query failed for " << intf->getName();
125                 return false;
126             }
127             return info && info.transfer == C2Color::TRANSFER_170M;
128         }
129 
QueryParamsForPreviousComponent(const std::shared_ptr<C2ComponentInterface> & intf,std::vector<std::unique_ptr<C2Param>> * params)130         static c2_status_t QueryParamsForPreviousComponent(
131                 [[maybe_unused]] const std::shared_ptr<C2ComponentInterface> &intf,
132                 std::vector<std::unique_ptr<C2Param>> *params) {
133             params->emplace_back(new C2StreamUsageTuning::output(
134                     0u, C2AndroidMemoryUsage::HW_TEXTURE_READ));
135             params->emplace_back(new C2StreamPixelFormatInfo::output(
136                     0u, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED));
137             return C2_OK;
138         }
139     private:
140         const c2_node_id_t mId;
141         struct Helper : public C2InterfaceHelper {
Helperandroid::SampleToneMappingFilter::Interface::Helper142             explicit Helper(std::shared_ptr<C2ReflectorHelper> reflector)
143                 : C2InterfaceHelper(reflector) {
144                 setDerivedInstance(this);
145 
146                 addParameter(
147                         DefineParam(mApiFeatures, C2_PARAMKEY_API_FEATURES)
148                         .withConstValue(new C2ApiFeaturesSetting(C2Config::api_feature_t(
149                                 API_REFLECTION |
150                                 API_VALUES |
151                                 API_CURRENT_VALUES |
152                                 API_DEPENDENCY |
153                                 API_SAME_INPUT_BUFFER)))
154                         .build());
155 
156                 mName = C2ComponentNameSetting::AllocShared(NAME.size() + 1);
157                 strncpy(mName->m.value, NAME.c_str(), NAME.size() + 1);
158                 addParameter(
159                         DefineParam(mName, C2_PARAMKEY_COMPONENT_NAME)
160                         .withConstValue(mName)
161                         .build());
162 
163                 addParameter(
164                         DefineParam(mKind, C2_PARAMKEY_COMPONENT_KIND)
165                         .withConstValue(new C2ComponentKindSetting(C2Component::KIND_OTHER))
166                         .build());
167 
168                 addParameter(
169                         DefineParam(mDomain, C2_PARAMKEY_COMPONENT_DOMAIN)
170                         .withConstValue(new C2ComponentDomainSetting(C2Component::DOMAIN_VIDEO))
171                         .build());
172 
173                 addParameter(
174                         DefineParam(mInputStreamCount, C2_PARAMKEY_INPUT_STREAM_COUNT)
175                         .withConstValue(new C2PortStreamCountTuning::input(1))
176                         .build());
177 
178                 addParameter(
179                         DefineParam(mOutputStreamCount, C2_PARAMKEY_OUTPUT_STREAM_COUNT)
180                         .withConstValue(new C2PortStreamCountTuning::output(1))
181                         .build());
182 
183                 addParameter(
184                         DefineParam(mInputFormat, C2_PARAMKEY_INPUT_STREAM_BUFFER_TYPE)
185                         .withConstValue(new C2StreamBufferTypeSetting::input(
186                                 0u, C2BufferData::GRAPHIC))
187                         .build());
188 
189                 static const std::string kRawMediaType = "video/raw";
190                 mInputMediaType = C2PortMediaTypeSetting::input::AllocShared(
191                         kRawMediaType.size() + 1);
192                 strncpy(mInputMediaType->m.value, kRawMediaType.c_str(), kRawMediaType.size() + 1);
193                 addParameter(
194                         DefineParam(mInputMediaType, C2_PARAMKEY_INPUT_MEDIA_TYPE)
195                         .withConstValue(mInputMediaType)
196                         .build());
197 
198                 addParameter(
199                         DefineParam(mOutputFormat, C2_PARAMKEY_OUTPUT_STREAM_BUFFER_TYPE)
200                         .withConstValue(new C2StreamBufferTypeSetting::output(
201                                 0u, C2BufferData::GRAPHIC))
202                         .build());
203 
204                 mOutputMediaType = C2PortMediaTypeSetting::output::AllocShared(
205                         kRawMediaType.size() + 1);
206                 strncpy(mOutputMediaType->m.value, kRawMediaType.c_str(), kRawMediaType.size() + 1);
207                 addParameter(
208                         DefineParam(mOutputMediaType, C2_PARAMKEY_OUTPUT_MEDIA_TYPE)
209                         .withConstValue(mOutputMediaType)
210                         .build());
211 
212                 addParameter(
213                         DefineParam(mActualInputDelay, C2_PARAMKEY_INPUT_DELAY)
214                         .withConstValue(new C2PortActualDelayTuning::input(0u))
215                         .build());
216 
217                 addParameter(
218                         DefineParam(mActualOutputDelay, C2_PARAMKEY_OUTPUT_DELAY)
219                         .withConstValue(new C2PortActualDelayTuning::output(0u))
220                         .build());
221 
222                 addParameter(
223                         DefineParam(mActualPipelineDelay, C2_PARAMKEY_PIPELINE_DELAY)
224                         .withConstValue(new C2ActualPipelineDelayTuning(0u))
225                         .build());
226 
227                 C2BlockPool::local_id_t outputPoolIds[1] = { C2BlockPool::BASIC_GRAPHIC };
228                 addParameter(
229                         DefineParam(mOutputPoolIds, C2_PARAMKEY_OUTPUT_BLOCK_POOLS)
230                         .withDefault(C2PortBlockPoolsTuning::output::AllocShared(outputPoolIds))
231                         .withFields({ C2F(mOutputPoolIds, m.values[0]).any(),
232                                       C2F(mOutputPoolIds, m.values).inRange(0, 1) })
233                         .withSetter(OutputBlockPoolSetter)
234                         .build());
235 
236                 addParameter(
237                         DefineParam(mInputHdrStaticInfo, C2_PARAMKEY_HDR_STATIC_INFO)
238                         .withDefault(new C2StreamHdrStaticInfo::input(0u))
239                         .withFields({
240                             C2F(mInputHdrStaticInfo, mastering.red.x).any(),
241                         })
242                         .withSetter(HdrStaticInfoSetter)
243                         .build());
244 
245                 addParameter(
246                         DefineParam(mOutputHdrStaticInfo, C2_PARAMKEY_HDR_STATIC_INFO)
247                         .withConstValue(new C2StreamHdrStaticInfo::output(0u))
248                         .build());
249 
250                 addParameter(
251                         DefineParam(mInputColorAspectInfo, C2_PARAMKEY_COLOR_ASPECTS)
252                         .withDefault(new C2StreamColorAspectsInfo::input(0u))
253                         .withFields({
254                             C2F(mInputColorAspectInfo, range).any(),
255                             C2F(mInputColorAspectInfo, primaries).any(),
256                             C2F(mInputColorAspectInfo, transfer).any(),
257                             C2F(mInputColorAspectInfo, matrix).any(),
258                         })
259                         .withSetter(InputColorAspectsSetter)
260                         .build());
261 
262                 addParameter(
263                         DefineParam(
264                             mColorAspectRequestInfo,
265                             (std::string(C2_PARAMKEY_COLOR_ASPECTS) + ".request").c_str())
266                         .withDefault(new C2StreamColorAspectsRequestInfo::output(0u))
267                         .withFields({
268                             C2F(mColorAspectRequestInfo, range).any(),
269                             C2F(mColorAspectRequestInfo, primaries).any(),
270                             C2F(mColorAspectRequestInfo, transfer).oneOf({
271                                 C2Color::TRANSFER_UNSPECIFIED,
272                                 C2Color::TRANSFER_170M,
273                             }),
274                             C2F(mColorAspectRequestInfo, matrix).any(),
275                         })
276                         .withSetter(ColorAspectsRequestSetter)
277                         .build());
278 
279                 addParameter(
280                         DefineParam(mVendorUltimateAnswerInfo, C2_PARAMKEY_VENDOR_ULTIMATE_ANSWER)
281                         .withDefault(new C2StreamVendorUltimateAnswerInfo::input(0u))
282                         .withFields({
283                             C2F(mVendorUltimateAnswerInfo, value).any(),
284                         })
285                         .withSetter(VendorUltimateAnswerSetter)
286                         .build());
287 
288                 addParameter(
289                         DefineParam(mOutputColorAspectInfo, C2_PARAMKEY_COLOR_ASPECTS)
290                         .withDefault(new C2StreamColorAspectsInfo::output(0u))
291                         .withFields({
292                             C2F(mOutputColorAspectInfo, range).any(),
293                             C2F(mOutputColorAspectInfo, primaries).any(),
294                             C2F(mOutputColorAspectInfo, transfer).any(),
295                             C2F(mOutputColorAspectInfo, matrix).any(),
296                         })
297                         .withSetter(OutputColorAspectsSetter,
298                                     mInputColorAspectInfo,
299                                     mColorAspectRequestInfo)
300                         .build());
301             }
302 
OutputBlockPoolSetterandroid::SampleToneMappingFilter::Interface::Helper303             static C2R OutputBlockPoolSetter(
304                     bool mayBlock,
305                     C2P<C2PortBlockPoolsTuning::output> &me) {
306                 (void)mayBlock, (void)me;
307                 return C2R::Ok();
308             }
309 
HdrStaticInfoSetterandroid::SampleToneMappingFilter::Interface::Helper310             static C2R HdrStaticInfoSetter(
311                     bool mayBlock,
312                     C2P<C2StreamHdrStaticInfo::input> &me) {
313                 (void)mayBlock, (void)me;
314                 return C2R::Ok();
315             }
316 
InputColorAspectsSetterandroid::SampleToneMappingFilter::Interface::Helper317             static C2R InputColorAspectsSetter(
318                     bool mayBlock,
319                     C2P<C2StreamColorAspectsInfo::input> &me) {
320                 (void)mayBlock, (void)me;
321                 return C2R::Ok();
322             }
323 
OutputColorAspectsSetterandroid::SampleToneMappingFilter::Interface::Helper324             static C2R OutputColorAspectsSetter(
325                     bool mayBlock,
326                     C2P<C2StreamColorAspectsInfo::output> &me,
327                     const C2P<C2StreamColorAspectsInfo::input> &inputColor,
328                     const C2P<C2StreamColorAspectsRequestInfo::output> &request) {
329                 (void)mayBlock;
330                 me.set().range = inputColor.v.range;
331                 me.set().primaries = inputColor.v.primaries;
332                 me.set().transfer = inputColor.v.transfer;
333                 if (request.v.transfer == C2Color::TRANSFER_170M) {
334                     me.set().transfer = C2Color::TRANSFER_170M;
335                 }
336                 me.set().matrix = inputColor.v.matrix;
337                 return C2R::Ok();
338             }
339 
ColorAspectsRequestSetterandroid::SampleToneMappingFilter::Interface::Helper340             static C2R ColorAspectsRequestSetter(
341                     bool mayBlock,
342                     C2P<C2StreamColorAspectsRequestInfo::output> &me) {
343                 (void)mayBlock;
344                 if (me.v.range != C2Color::RANGE_UNSPECIFIED) {
345                     me.set().range = C2Color::RANGE_UNSPECIFIED;
346                 }
347                 if (me.v.primaries != C2Color::PRIMARIES_UNSPECIFIED) {
348                     me.set().primaries = C2Color::PRIMARIES_UNSPECIFIED;
349                 }
350                 if (me.v.transfer != C2Color::TRANSFER_170M) {
351                     me.set().transfer = C2Color::TRANSFER_UNSPECIFIED;
352                 }
353                 if (me.v.matrix != C2Color::MATRIX_UNSPECIFIED) {
354                     me.set().matrix = C2Color::MATRIX_UNSPECIFIED;
355                 }
356                 return C2R::Ok();
357             }
358 
VendorUltimateAnswerSetterandroid::SampleToneMappingFilter::Interface::Helper359             static C2R VendorUltimateAnswerSetter(
360                     bool mayBlock,
361                     C2P<C2StreamVendorUltimateAnswerInfo::input> &me) {
362                 (void)mayBlock;
363                 ALOGI("Answer to the Ultimate Question of Life, the Universe, and Everything "
364                       "set to %d", me.v.value);
365                 return C2R::Ok();
366             }
367 
368             std::shared_ptr<C2ApiFeaturesSetting> mApiFeatures;
369 
370             std::shared_ptr<C2ComponentNameSetting> mName;
371             std::shared_ptr<C2ComponentAliasesSetting> mAliases;
372             std::shared_ptr<C2ComponentKindSetting> mKind;
373             std::shared_ptr<C2ComponentDomainSetting> mDomain;
374 
375             std::shared_ptr<C2PortMediaTypeSetting::input> mInputMediaType;
376             std::shared_ptr<C2PortMediaTypeSetting::output> mOutputMediaType;
377             std::shared_ptr<C2StreamBufferTypeSetting::input> mInputFormat;
378             std::shared_ptr<C2StreamBufferTypeSetting::output> mOutputFormat;
379 
380             std::shared_ptr<C2PortActualDelayTuning::input> mActualInputDelay;
381             std::shared_ptr<C2PortActualDelayTuning::output> mActualOutputDelay;
382             std::shared_ptr<C2ActualPipelineDelayTuning> mActualPipelineDelay;
383 
384             std::shared_ptr<C2PortStreamCountTuning::input> mInputStreamCount;
385             std::shared_ptr<C2PortStreamCountTuning::output> mOutputStreamCount;
386 
387             std::shared_ptr<C2PortBlockPoolsTuning::output> mOutputPoolIds;
388 
389             std::shared_ptr<C2StreamHdrStaticInfo::input> mInputHdrStaticInfo;
390             std::shared_ptr<C2StreamHdrStaticInfo::output> mOutputHdrStaticInfo;
391             std::shared_ptr<C2StreamColorAspectsInfo::input> mInputColorAspectInfo;
392             std::shared_ptr<C2StreamColorAspectsInfo::output> mOutputColorAspectInfo;
393             std::shared_ptr<C2StreamColorAspectsRequestInfo::output> mColorAspectRequestInfo;
394 
395             std::shared_ptr<C2StreamVendorUltimateAnswerInfo::input> mVendorUltimateAnswerInfo;
396         } mHelper;
397     };
398 
SampleToneMappingFilter(c2_node_id_t id,const std::shared_ptr<C2ReflectorHelper> & reflector)399     SampleToneMappingFilter(c2_node_id_t id, const std::shared_ptr<C2ReflectorHelper> &reflector)
400         : mIntf(std::make_shared<Interface>(id, reflector)) {
401     }
~SampleToneMappingFilter()402     ~SampleToneMappingFilter() override {
403         if (mProcessingThread.joinable()) {
404             mProcessingThread.join();
405         }
406     }
407 
setListener_vb(const std::shared_ptr<Listener> & listener,c2_blocking_t mayBlock)408     c2_status_t setListener_vb(
409             const std::shared_ptr<Listener> &listener, c2_blocking_t mayBlock) override {
410         std::chrono::steady_clock::time_point deadline = std::chrono::steady_clock::now() + 5ms;
411         {
412             std::unique_lock lock(mStateMutex);
413             if (mState == RELEASED) {
414                 return C2_BAD_STATE;
415             }
416             if (mState == RUNNING && listener) {
417                 return C2_BAD_STATE;
418             }
419             if (mState != STOPPED) {
420                 return C2_BAD_STATE;
421             }
422         }
423         std::unique_lock lock(mListenerMutex, std::try_to_lock);
424         if (lock) {
425             mListener = listener;
426             return C2_OK;
427         }
428         if (mayBlock == C2_DONT_BLOCK) {
429             return C2_BLOCKING;
430         }
431         lock.try_lock_until(deadline);
432         if (!lock) {
433             return C2_TIMED_OUT;
434         }
435         mListener = listener;
436         return C2_OK;
437     }
438 
queue_nb(std::list<std::unique_ptr<C2Work>> * const items)439     c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override {
440         if (!items) {
441             return C2_BAD_VALUE;
442         }
443         {
444             std::unique_lock lock(mStateMutex);
445             if (mState != RUNNING) {
446                 return C2_BAD_STATE;
447             }
448         }
449         std::unique_lock lock(mQueueMutex);
450         mQueue.splice(mQueue.end(), *items);
451         mQueueCondition.notify_all();
452         return C2_OK;
453     }
454 
announce_nb(const std::vector<C2WorkOutline> &)455     c2_status_t announce_nb(const std::vector<C2WorkOutline> &) override { return C2_OMITTED; }
456 
flush_sm(flush_mode_t mode,std::list<std::unique_ptr<C2Work>> * const flushedWork)457     c2_status_t flush_sm(
458             flush_mode_t mode,
459             std::list<std::unique_ptr<C2Work>>* const flushedWork) override {
460         if (!flushedWork) {
461             return C2_BAD_VALUE;
462         }
463         if (mode == FLUSH_CHAIN) {
464             return C2_BAD_VALUE;
465         }
466         {
467             std::unique_lock lock(mStateMutex);
468             if (mState != RUNNING) {
469                 return C2_BAD_STATE;
470             }
471         }
472         {
473             std::unique_lock lock(mQueueMutex);
474             mQueue.swap(*flushedWork);
475         }
476         // NOTE: this component does not have internal state to flush.
477         return C2_OK;
478     }
479 
drain_nb(drain_mode_t mode)480     c2_status_t drain_nb(drain_mode_t mode) override {
481         if (mode == DRAIN_CHAIN) {
482             return C2_BAD_VALUE;
483         }
484         {
485             std::unique_lock lock(mStateMutex);
486             if (mState != RUNNING) {
487                 return C2_BAD_STATE;
488             }
489         }
490         // NOTE: this component does not wait for work items before processing.
491         return C2_OK;
492     }
493 
start()494     c2_status_t start() override {
495         //std::chrono::steady_clock::time_point deadline = std::chrono::steady_clock::now() + 500ms;
496         {
497             std::unique_lock lock(mStateMutex);
498             if (mState == STARTING) {
499                 return C2_DUPLICATE;
500             }
501             if (mState != STOPPED) {
502                 return C2_BAD_STATE;
503             }
504             mState = STARTING;
505         }
506         {
507             std::unique_lock lock(mProcessingMutex);
508             if (!mProcessingThread.joinable()) {
509                 mProcessingThread = std::thread([this]() {
510                     processLoop(shared_from_this());
511                 });
512             }
513         }
514         {
515             std::unique_lock lock(mStateMutex);
516             mState = RUNNING;
517         }
518         return C2_OK;
519     }
520 
stop()521     c2_status_t stop() override {
522         //std::chrono::steady_clock::time_point deadline = std::chrono::steady_clock::now() + 500ms;
523         {
524             std::unique_lock lock(mStateMutex);
525             if (mState == STOPPING) {
526                 return C2_DUPLICATE;
527             }
528             if (mState != RUNNING) {
529                 return C2_BAD_STATE;
530             }
531             mState = STOPPING;
532         }
533         {
534             std::unique_lock lock(mQueueMutex);
535             mQueueCondition.notify_all();
536         }
537         {
538             std::unique_lock lock(mProcessingMutex);
539             if (mProcessingThread.joinable()) {
540                 mProcessingThread.join();
541             }
542         }
543         {
544             std::unique_lock lock(mStateMutex);
545             mState = STOPPED;
546         }
547         return C2_OK;
548     }
549 
reset()550     c2_status_t reset() override {
551         //std::chrono::steady_clock::time_point deadline = std::chrono::steady_clock::now() + 500ms;
552         {
553             std::unique_lock lock(mStateMutex);
554             if (mState == RESETTING) {
555                 return C2_DUPLICATE;
556             }
557             if (mState == RELEASED) {
558                 return C2_BAD_STATE;
559             }
560             mState = RESETTING;
561         }
562         {
563             std::unique_lock lock(mQueueMutex);
564             mQueueCondition.notify_all();
565         }
566         {
567             std::unique_lock lock(mProcessingMutex);
568             if (mProcessingThread.joinable()) {
569                 mProcessingThread.join();
570             }
571         }
572         {
573             std::unique_lock lock(mStateMutex);
574             mState = STOPPED;
575         }
576         return C2_OK;
577     }
578 
release()579     c2_status_t release() override {
580         //std::chrono::steady_clock::time_point deadline = std::chrono::steady_clock::now() + 500ms;
581         {
582             std::unique_lock lock(mStateMutex);
583             if (mState == RELEASED || mState == RELEASING) {
584                 return C2_DUPLICATE;
585             }
586             // TODO: return C2_BAD_STATE if not stopped
587             mState = RELEASING;
588         }
589         {
590             std::unique_lock lock(mQueueMutex);
591             mQueueCondition.notify_all();
592         }
593         {
594             std::unique_lock lock(mProcessingMutex);
595             if (mProcessingThread.joinable()) {
596                 mProcessingThread.join();
597             }
598         }
599         {
600             std::unique_lock lock(mStateMutex);
601             mState = RELEASED;
602         }
603         return C2_OK;
604     }
605 
intf()606     std::shared_ptr<C2ComponentInterface> intf() override {
607         return mIntf;
608     }
609 
610 private:
processLoop(std::shared_ptr<SampleToneMappingFilter> thiz)611     void processLoop(std::shared_ptr<SampleToneMappingFilter> thiz) {
612         constexpr float kDefaultMaxLumiance = 500.0;
613         constexpr float kDefaultMaxMasteringLuminance = 1000.0;
614         constexpr float kDefaultMaxContentLuminance = 1000.0;
615         constexpr uint32_t kDstUsage =
616                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
617                 GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
618 
619         int32_t workCount = 0;
620         std::unique_ptr<renderengine::RenderEngine> renderEngine = renderengine::RenderEngine::create(
621                 renderengine::RenderEngineCreationArgs::Builder()
622                     .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
623                     .setImageCacheSize(2 /*maxFrameBufferAcquiredBuffers*/)
624                     .setUseColorManagerment(true)
625                     .setEnableProtectedContext(false)
626                     .setPrecacheToneMapperShaderOnly(true)
627                     .setContextPriority(renderengine::RenderEngine::ContextPriority::LOW)
628                     .build());
629         if (!renderEngine) {
630             std::unique_lock lock(mListenerMutex);
631             mListener->onError_nb(thiz, C2_CORRUPTED);
632             return;
633         }
634         uint32_t textureName = 0;
635         renderEngine->genTextures(1, &textureName);
636 
637         while (true) {
638             // Before doing anything, verify the state
639             {
640                 std::unique_lock lock(mStateMutex);
641                 if (mState != RUNNING) {
642                     break;
643                 }
644             }
645             // Extract one work item
646             std::unique_ptr<C2Work> work;
647             {
648                 std::unique_lock lock(mQueueMutex);
649                 if (mQueue.empty()) {
650                     mQueueCondition.wait_for(lock, 1s);
651                 }
652                 if (mQueue.empty()) {
653                     continue;
654                 }
655                 mQueue.front().swap(work);
656                 mQueue.pop_front();
657                 ++workCount;
658             }
659             LOG(VERBOSE) << "work #" << workCount << ": flags=" << work->input.flags
660                     << " timestamp=" << work->input.ordinal.timestamp.peek();;
661 
662             std::vector<C2Param *> configUpdate;
663             for (const std::unique_ptr<C2Param> &param : work->input.configUpdate) {
664                 configUpdate.push_back(param.get());
665             }
666             std::vector<std::unique_ptr<C2SettingResult>> failures;
667             mIntf->config_vb(configUpdate, C2_MAY_BLOCK, &failures);
668 
669             std::shared_ptr<C2StreamHdrStaticInfo::input> hdrStaticInfo =
670                 mIntf->getHdrStaticMetadata();
671             uint32_t dataspace = mIntf->getDataSpace();
672 
673             std::shared_ptr<C2Buffer> buffer;
674             if (!work->input.buffers.empty()) {
675                 buffer = work->input.buffers.front();
676             }
677             std::shared_ptr<C2Buffer> outC2Buffer;
678             status_t err = OK;
679             if (buffer) {
680                 if (buffer->hasInfo(C2StreamHdrStaticInfo::output::PARAM_TYPE)) {
681                     std::shared_ptr<const C2Info> info =
682                         buffer->getInfo(C2StreamHdrStaticInfo::output::PARAM_TYPE);
683                     std::unique_ptr<C2Param> flipped = C2Param::CopyAsStream(
684                             *info, false /* output */, info->stream());
685                     hdrStaticInfo.reset(static_cast<C2StreamHdrStaticInfo::input *>(
686                             flipped.release()));
687                 }
688                 const C2Handle *c2Handle =
689                     buffer->data().graphicBlocks().front().handle();
690                 uint32_t width, height, format, stride, igbp_slot, generation;
691                 uint64_t usage, igbp_id;
692                 _UnwrapNativeCodec2GrallocMetadata(
693                         c2Handle, &width, &height, &format, &usage, &stride, &generation,
694                         &igbp_id, &igbp_slot);
695                 native_handle_t *grallocHandle = UnwrapNativeCodec2GrallocHandle(c2Handle);
696                 sp<GraphicBuffer> srcBuffer = new GraphicBuffer(
697                         grallocHandle, GraphicBuffer::CLONE_HANDLE,
698                         width, height, format, 1, usage, stride);
699 
700                 native_handle_delete(grallocHandle);
701                 std::shared_ptr<C2GraphicBlock> dstBlock;
702                 C2BlockPool::local_id_t poolId = mIntf->getPoolId();
703                 std::shared_ptr<C2BlockPool> pool;
704                 GetCodec2BlockPool(poolId, thiz, &pool);
705                 pool->fetchGraphicBlock(
706                         width, height, HAL_PIXEL_FORMAT_RGBA_8888, C2AndroidMemoryUsage::FromGrallocUsage(kDstUsage),
707                         &dstBlock);
708                 outC2Buffer = C2Buffer::CreateGraphicBuffer(
709                         dstBlock->share(C2Rect(width, height), C2Fence()));
710                 c2Handle = dstBlock->handle();
711                 _UnwrapNativeCodec2GrallocMetadata(
712                         c2Handle, &width, &height, &format, &usage, &stride, &generation,
713                         &igbp_id, &igbp_slot);
714                 grallocHandle = UnwrapNativeCodec2GrallocHandle(c2Handle);
715                 sp<GraphicBuffer> dstBuffer = new GraphicBuffer(
716                         grallocHandle, GraphicBuffer::CLONE_HANDLE,
717                         width, height, format, 1, usage, stride);
718 
719                 native_handle_delete(grallocHandle);
720                 Rect sourceCrop(0, 0, width, height);
721 
722                 renderengine::DisplaySettings clientCompositionDisplay;
723                 std::vector<const renderengine::LayerSettings*> clientCompositionLayers;
724 
725                 clientCompositionDisplay.physicalDisplay = sourceCrop;
726                 clientCompositionDisplay.clip = sourceCrop;
727 
728                 clientCompositionDisplay.outputDataspace = ui::Dataspace::V0_SRGB;
729                 clientCompositionDisplay.maxLuminance = kDefaultMaxLumiance;
730                 clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
731                 renderengine::LayerSettings layerSettings;
732                 layerSettings.geometry.boundaries = sourceCrop.toFloatRect();
733                 layerSettings.alpha = 1.0f;
734 
735                 layerSettings.sourceDataspace = static_cast<ui::Dataspace>(dataspace);
736 
737                 // from BufferLayer
738                 layerSettings.source.buffer.buffer = srcBuffer;
739                 layerSettings.source.buffer.isOpaque = true;
740                 // TODO: fence
741                 layerSettings.source.buffer.fence = Fence::NO_FENCE;
742                 layerSettings.source.buffer.textureName = textureName;
743                 layerSettings.source.buffer.usePremultipliedAlpha = false;
744                 layerSettings.source.buffer.maxMasteringLuminance =
745                     (hdrStaticInfo && *hdrStaticInfo &&
746                      hdrStaticInfo->mastering.maxLuminance > 0 &&
747                      hdrStaticInfo->mastering.minLuminance > 0)
748                         ? hdrStaticInfo->mastering.maxLuminance : kDefaultMaxMasteringLuminance;
749                 layerSettings.source.buffer.maxContentLuminance =
750                     (hdrStaticInfo && *hdrStaticInfo && hdrStaticInfo->maxCll > 0)
751                         ? hdrStaticInfo->maxCll : kDefaultMaxContentLuminance;
752 
753                 // Set filtering to false since the capture itself doesn't involve
754                 // any scaling, metadata retriever JNI is scaling the bitmap if
755                 // display size is different from decoded size. If that scaling
756                 // needs to be handled by server side, consider enable this based
757                 // display size vs decoded size.
758                 layerSettings.source.buffer.useTextureFiltering = false;
759                 layerSettings.source.buffer.textureTransform = mat4();
760                 clientCompositionLayers.push_back(&layerSettings);
761 
762                 // Use an empty fence for the buffer fence, since we just created the buffer so
763                 // there is no need for synchronization with the GPU.
764                 base::unique_fd bufferFence;
765                 base::unique_fd drawFence;
766                 renderEngine->useProtectedContext(false);
767                 err = renderEngine->drawLayers(
768                         clientCompositionDisplay, clientCompositionLayers, dstBuffer.get(),
769                         /*useFramebufferCache=*/false, std::move(bufferFence), &drawFence);
770 
771                 sp<Fence> fence = new Fence(std::move(drawFence));
772 
773                 // We can move waiting for fence & sending it back on a separate thread to improve
774                 // efficiency, but leaving it here for simplicity.
775                 if (err != OK) {
776                     LOG(ERROR) << "drawLayers returned err " << err;
777                 } else {
778                     err = fence->wait(500);
779                     if (err != OK) {
780                         LOG(WARNING) << "wait for fence returned err " << err;
781                     }
782                 }
783                 renderEngine->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL);
784             }
785 
786             work->worklets.front()->output.ordinal = work->input.ordinal;
787             work->worklets.front()->output.flags = work->input.flags;
788             if (err == OK) {
789                 work->workletsProcessed = 1;
790                 if (outC2Buffer) {
791                     work->worklets.front()->output.buffers.push_back(outC2Buffer);
792                 }
793                 work->result = C2_OK;
794             } else {
795                 work->result = C2_CORRUPTED;
796             }
797             std::list<std::unique_ptr<C2Work>> items;
798             items.push_back(std::move(work));
799 
800             std::unique_lock lock(mListenerMutex);
801             mListener->onWorkDone_nb(thiz, std::move(items));
802             LOG(VERBOSE) << "sent work #" << workCount;
803         }
804     }
805 
806     mutable std::timed_mutex mListenerMutex;
807     std::shared_ptr<Listener> mListener;
808 
809     mutable std::mutex mQueueMutex;
810     mutable std::condition_variable mQueueCondition;
811     std::list<std::unique_ptr<C2Work>> mQueue;
812 
813     const std::shared_ptr<Interface> mIntf;
814 
815     mutable std::mutex mStateMutex;
816     enum State {
817         STOPPED,
818         RUNNING,
819         RELEASED,
820         STARTING,   // STOPPED -> RUNNING
821         STOPPING,   // RUNNING -> STOPPED
822         RESETTING,  // <<ANY>> -> STOPPED
823         RELEASING,  // STOPPED -> RELEASED
824     } mState;
825 
826     mutable std::mutex mProcessingMutex;
827     std::thread mProcessingThread;
828 
829 };
830 
831 // static
832 const std::string SampleToneMappingFilter::Interface::NAME = "c2.sample.tone-mapper";
833 // static
834 const FilterPlugin_V1::Descriptor SampleToneMappingFilter::Interface::DESCRIPTOR = {
835     // controlParams
836     {
837         C2StreamColorAspectsRequestInfo::output::PARAM_TYPE,
838         C2StreamVendorUltimateAnswerInfo::input::PARAM_TYPE,
839     },
840     // affectedParams
841     {
842         C2StreamHdrStaticInfo::output::PARAM_TYPE,
843         C2StreamColorAspectsInfo::output::PARAM_TYPE,
844     },
845 };
846 
847 class SampleC2ComponentStore : public C2ComponentStore {
848 public:
SampleC2ComponentStore()849     SampleC2ComponentStore()
850         : mReflector(std::make_shared<C2ReflectorHelper>()),
851           mIntf(mReflector),
852           mFactories(CreateFactories(mReflector)) {
853     }
854     ~SampleC2ComponentStore() = default;
855 
getName() const856     C2String getName() const override { return "android.sample.filter-plugin-store"; }
createComponent(C2String name,std::shared_ptr<C2Component> * const component)857     c2_status_t createComponent(
858             C2String name, std::shared_ptr<C2Component>* const component) override {
859         if (mFactories.count(name) == 0) {
860             return C2_BAD_VALUE;
861         }
862         return mFactories.at(name)->createComponent(++mNodeId, component);
863     }
createInterface(C2String name,std::shared_ptr<C2ComponentInterface> * const interface)864     c2_status_t createInterface(
865             C2String name, std::shared_ptr<C2ComponentInterface>* const interface) override {
866         if (mFactories.count(name) == 0) {
867             return C2_BAD_VALUE;
868         }
869         return mFactories.at(name)->createInterface(++mNodeId, interface);
870     }
listComponents()871     std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override {
872         std::vector<std::shared_ptr<const C2Component::Traits>> ret;
873         for (const auto &[name, factory] : mFactories) {
874             ret.push_back(factory->getTraits());
875         }
876         return ret;
877     }
copyBuffer(std::shared_ptr<C2GraphicBuffer>,std::shared_ptr<C2GraphicBuffer>)878     c2_status_t copyBuffer(
879             std::shared_ptr<C2GraphicBuffer>, std::shared_ptr<C2GraphicBuffer>) override {
880         return C2_OMITTED;
881     }
query_sm(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,std::vector<std::unique_ptr<C2Param>> * const heapParams) const882     c2_status_t query_sm(
883             const std::vector<C2Param*> &stackParams,
884             const std::vector<C2Param::Index> &heapParamIndices,
885             std::vector<std::unique_ptr<C2Param>>* const heapParams) const override {
886         return mIntf.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
887     }
config_sm(const std::vector<C2Param * > & params,std::vector<std::unique_ptr<C2SettingResult>> * const failures)888     c2_status_t config_sm(
889             const std::vector<C2Param*> &params,
890             std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
891         return mIntf.config(params, C2_MAY_BLOCK, failures);
892     }
getParamReflector() const893     std::shared_ptr<C2ParamReflector> getParamReflector() const override {
894         return mReflector;
895     }
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const896     c2_status_t querySupportedParams_nb(
897             std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override {
898         return mIntf.querySupportedParams(params);
899     }
querySupportedValues_sm(std::vector<C2FieldSupportedValuesQuery> & fields) const900     c2_status_t querySupportedValues_sm(
901             std::vector<C2FieldSupportedValuesQuery> &fields) const override {
902         return mIntf.querySupportedValues(fields, C2_MAY_BLOCK);
903     }
904 
905 private:
906     class ComponentFactory {
907     public:
908         virtual ~ComponentFactory() = default;
909 
getTraits()910         const std::shared_ptr<const C2Component::Traits> &getTraits() { return mTraits; }
911 
912         virtual c2_status_t createComponent(
913                 c2_node_id_t id,
914                 std::shared_ptr<C2Component>* const component) const = 0;
915         virtual c2_status_t createInterface(
916                 c2_node_id_t id,
917                 std::shared_ptr<C2ComponentInterface>* const interface) const = 0;
918     protected:
ComponentFactory(const std::shared_ptr<const C2Component::Traits> & traits)919         ComponentFactory(const std::shared_ptr<const C2Component::Traits> &traits)
920             : mTraits(traits) {
921         }
922     private:
923         const std::shared_ptr<const C2Component::Traits> mTraits;
924     };
925 
926     template <class T>
927     struct ComponentFactoryImpl : public ComponentFactory {
928     public:
ComponentFactoryImplandroid::SampleC2ComponentStore::ComponentFactoryImpl929         ComponentFactoryImpl(
930                 const std::shared_ptr<const C2Component::Traits> &traits,
931                 const std::shared_ptr<C2ReflectorHelper> &reflector)
932             : ComponentFactory(traits),
933               mReflector(reflector) {
934         }
935         ~ComponentFactoryImpl() override = default;
createComponentandroid::SampleC2ComponentStore::ComponentFactoryImpl936         c2_status_t createComponent(
937                 c2_node_id_t id,
938                 std::shared_ptr<C2Component>* const component) const override {
939             *component = std::make_shared<T>(id, mReflector);
940             return C2_OK;
941         }
createInterfaceandroid::SampleC2ComponentStore::ComponentFactoryImpl942         c2_status_t createInterface(
943                 c2_node_id_t id,
944                 std::shared_ptr<C2ComponentInterface>* const interface) const override {
945             *interface = std::make_shared<typename T::Interface>(id, mReflector);
946             return C2_OK;
947         }
948     private:
949         std::shared_ptr<C2ReflectorHelper> mReflector;
950     };
951 
952     template <class T>
AddFactory(std::map<C2String,std::unique_ptr<ComponentFactory>> * factories,const std::shared_ptr<C2ReflectorHelper> & reflector)953     static void AddFactory(
954             std::map<C2String, std::unique_ptr<ComponentFactory>> *factories,
955             const std::shared_ptr<C2ReflectorHelper> &reflector) {
956         std::shared_ptr<C2ComponentInterface> intf{new typename T::Interface(0, reflector)};
957         std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
958         CHECK(C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf))
959                 << "Failed to fill traits from interface";
960         factories->emplace(
961                 traits->name,
962                 new ComponentFactoryImpl<T>(traits, reflector));
963     }
964 
CreateFactories(const std::shared_ptr<C2ReflectorHelper> & reflector)965     static std::map<C2String, std::unique_ptr<ComponentFactory>> CreateFactories(
966             const std::shared_ptr<C2ReflectorHelper> &reflector) {
967         std::map<C2String, std::unique_ptr<ComponentFactory>> factories;
968         AddFactory<SampleToneMappingFilter>(&factories, reflector);
969         return factories;
970     }
971 
972 
973     std::shared_ptr<C2ReflectorHelper> mReflector;
974     struct Interface : public C2InterfaceHelper {
Interfaceandroid::SampleC2ComponentStore::Interface975         explicit Interface(std::shared_ptr<C2ReflectorHelper> reflector)
976             : C2InterfaceHelper(reflector) {
977         }
978     } mIntf;
979 
980     const std::map<C2String, std::unique_ptr<ComponentFactory>> mFactories;
981 
982     std::atomic_int32_t mNodeId{0};
983 };
984 
985 class SampleFilterPlugin : public FilterPlugin_V1 {
986 public:
SampleFilterPlugin()987     SampleFilterPlugin() : mStore(new SampleC2ComponentStore) {}
988     ~SampleFilterPlugin() override = default;
989 
getComponentStore()990     std::shared_ptr<C2ComponentStore> getComponentStore() override {
991         return mStore;
992     }
993 
describe(C2String name,Descriptor * desc)994     bool describe(C2String name, Descriptor *desc) override {
995         if (name == SampleToneMappingFilter::Interface::NAME) {
996             *desc = SampleToneMappingFilter::Interface::DESCRIPTOR;
997             return true;
998         }
999         return false;
1000     }
1001 
isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> & intf)1002     bool isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> &intf) override {
1003         if (intf->getName() == SampleToneMappingFilter::Interface::NAME) {
1004             return SampleToneMappingFilter::Interface::IsFilteringEnabled(intf);
1005         }
1006         return false;
1007     }
1008 
queryParamsForPreviousComponent(const std::shared_ptr<C2ComponentInterface> & intf,std::vector<std::unique_ptr<C2Param>> * params)1009     c2_status_t queryParamsForPreviousComponent(
1010             const std::shared_ptr<C2ComponentInterface> &intf,
1011             std::vector<std::unique_ptr<C2Param>> *params) override {
1012         if (intf->getName() == SampleToneMappingFilter::Interface::NAME) {
1013             return SampleToneMappingFilter::Interface::QueryParamsForPreviousComponent(
1014                     intf, params);
1015         }
1016         return C2_BAD_VALUE;
1017     }
1018 
1019 private:
1020     std::shared_ptr<C2ComponentStore> mStore;
1021 };
1022 
1023 }  // namespace android
1024 
1025 extern "C" {
1026 
GetFilterPluginVersion()1027 int32_t GetFilterPluginVersion() {
1028     return ::android::SampleFilterPlugin::VERSION;
1029 }
1030 
CreateFilterPlugin()1031 void *CreateFilterPlugin() {
1032     return new ::android::SampleFilterPlugin;
1033 }
1034 
DestroyFilterPlugin(void * plugin)1035 void DestroyFilterPlugin(void *plugin) {
1036     delete (::android::SampleFilterPlugin *)plugin;
1037 }
1038 
1039 }  // extern "C"
1040