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