• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
QueryParamsForPreviousComponent(const std::shared_ptr<C2ComponentInterface> & intf,std::vector<std::unique_ptr<C2Param>> * params)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         mQueueCondition.notify_all();
421         return C2_OK;
422     }
423 
announce_nb(const std::vector<C2WorkOutline> &)424     c2_status_t announce_nb(const std::vector<C2WorkOutline> &) override { return C2_OMITTED; }
425 
flush_sm(flush_mode_t mode,std::list<std::unique_ptr<C2Work>> * const flushedWork)426     c2_status_t flush_sm(
427             flush_mode_t mode,
428             std::list<std::unique_ptr<C2Work>>* const flushedWork) override {
429         if (!flushedWork) {
430             return C2_BAD_VALUE;
431         }
432         if (mode == FLUSH_CHAIN) {
433             return C2_BAD_VALUE;
434         }
435         {
436             std::unique_lock lock(mStateMutex);
437             if (mState != RUNNING) {
438                 return C2_BAD_STATE;
439             }
440         }
441         {
442             std::unique_lock lock(mQueueMutex);
443             mQueue.swap(*flushedWork);
444         }
445         // NOTE: this component does not have internal state to flush.
446         return C2_OK;
447     }
448 
drain_nb(drain_mode_t mode)449     c2_status_t drain_nb(drain_mode_t mode) override {
450         if (mode == DRAIN_CHAIN) {
451             return C2_BAD_VALUE;
452         }
453         {
454             std::unique_lock lock(mStateMutex);
455             if (mState != RUNNING) {
456                 return C2_BAD_STATE;
457             }
458         }
459         // NOTE: this component does not wait for work items before processing.
460         return C2_OK;
461     }
462 
start()463     c2_status_t start() override {
464         //std::chrono::steady_clock::time_point deadline = std::chrono::steady_clock::now() + 500ms;
465         {
466             std::unique_lock lock(mStateMutex);
467             if (mState == STARTING) {
468                 return C2_DUPLICATE;
469             }
470             if (mState != STOPPED) {
471                 return C2_BAD_STATE;
472             }
473             mState = STARTING;
474         }
475         {
476             std::unique_lock lock(mProcessingMutex);
477             if (!mProcessingThread.joinable()) {
478                 mProcessingThread = std::thread([this]() {
479                     processLoop(shared_from_this());
480                 });
481             }
482         }
483         {
484             std::unique_lock lock(mStateMutex);
485             mState = RUNNING;
486         }
487         return C2_OK;
488     }
489 
stop()490     c2_status_t stop() override {
491         //std::chrono::steady_clock::time_point deadline = std::chrono::steady_clock::now() + 500ms;
492         {
493             std::unique_lock lock(mStateMutex);
494             if (mState == STOPPING) {
495                 return C2_DUPLICATE;
496             }
497             if (mState != RUNNING) {
498                 return C2_BAD_STATE;
499             }
500             mState = STOPPING;
501         }
502         {
503             std::unique_lock lock(mQueueMutex);
504             mQueueCondition.notify_all();
505         }
506         {
507             std::unique_lock lock(mProcessingMutex);
508             if (mProcessingThread.joinable()) {
509                 mProcessingThread.join();
510             }
511         }
512         {
513             std::unique_lock lock(mStateMutex);
514             mState = STOPPED;
515         }
516         return C2_OK;
517     }
518 
reset()519     c2_status_t reset() override {
520         //std::chrono::steady_clock::time_point deadline = std::chrono::steady_clock::now() + 500ms;
521         {
522             std::unique_lock lock(mStateMutex);
523             if (mState == RESETTING) {
524                 return C2_DUPLICATE;
525             }
526             if (mState == RELEASED) {
527                 return C2_BAD_STATE;
528             }
529             mState = RESETTING;
530         }
531         {
532             std::unique_lock lock(mQueueMutex);
533             mQueueCondition.notify_all();
534         }
535         {
536             std::unique_lock lock(mProcessingMutex);
537             if (mProcessingThread.joinable()) {
538                 mProcessingThread.join();
539             }
540         }
541         {
542             std::unique_lock lock(mStateMutex);
543             mState = STOPPED;
544         }
545         return C2_OK;
546     }
547 
release()548     c2_status_t release() override {
549         //std::chrono::steady_clock::time_point deadline = std::chrono::steady_clock::now() + 500ms;
550         {
551             std::unique_lock lock(mStateMutex);
552             if (mState == RELEASED || mState == RELEASING) {
553                 return C2_DUPLICATE;
554             }
555             // TODO: return C2_BAD_STATE if not stopped
556             mState = RELEASING;
557         }
558         {
559             std::unique_lock lock(mQueueMutex);
560             mQueueCondition.notify_all();
561         }
562         {
563             std::unique_lock lock(mProcessingMutex);
564             if (mProcessingThread.joinable()) {
565                 mProcessingThread.join();
566             }
567         }
568         {
569             std::unique_lock lock(mStateMutex);
570             mState = RELEASED;
571         }
572         return C2_OK;
573     }
574 
intf()575     std::shared_ptr<C2ComponentInterface> intf() override {
576         return mIntf;
577     }
578 
579 private:
processLoop(std::shared_ptr<SampleToneMappingFilter> thiz)580     void processLoop(std::shared_ptr<SampleToneMappingFilter> thiz) {
581         constexpr float kDefaultMaxLumiance = 500.0;
582         constexpr float kDefaultMaxMasteringLuminance = 1000.0;
583         constexpr float kDefaultMaxContentLuminance = 1000.0;
584         constexpr uint32_t kDstUsage =
585                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
586                 GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
587 
588         int32_t workCount = 0;
589         std::unique_ptr<renderengine::RenderEngine> renderEngine = renderengine::RenderEngine::create(
590                 renderengine::RenderEngineCreationArgs::Builder()
591                     .setPixelFormat(static_cast<int>(ui::PixelFormat::RGBA_8888))
592                     .setImageCacheSize(2 /*maxFrameBufferAcquiredBuffers*/)
593                     .setUseColorManagerment(true)
594                     .setEnableProtectedContext(false)
595                     .setPrecacheToneMapperShaderOnly(true)
596                     .setContextPriority(renderengine::RenderEngine::ContextPriority::LOW)
597                     .build());
598         if (!renderEngine) {
599             std::unique_lock lock(mListenerMutex);
600             mListener->onError_nb(thiz, C2_CORRUPTED);
601             return;
602         }
603         uint32_t textureName = 0;
604         renderEngine->genTextures(1, &textureName);
605 
606         while (true) {
607             // Before doing anything, verify the state
608             {
609                 std::unique_lock lock(mStateMutex);
610                 if (mState != RUNNING) {
611                     break;
612                 }
613             }
614             // Extract one work item
615             std::unique_ptr<C2Work> work;
616             {
617                 std::unique_lock lock(mQueueMutex);
618                 if (mQueue.empty()) {
619                     mQueueCondition.wait_for(lock, 1s);
620                 }
621                 if (mQueue.empty()) {
622                     continue;
623                 }
624                 mQueue.front().swap(work);
625                 mQueue.pop_front();
626                 ++workCount;
627             }
628             LOG(VERBOSE) << "work #" << workCount << ": flags=" << work->input.flags
629                     << " timestamp=" << work->input.ordinal.timestamp.peek();;
630 
631             std::vector<C2Param *> configUpdate;
632             for (const std::unique_ptr<C2Param> &param : work->input.configUpdate) {
633                 configUpdate.push_back(param.get());
634             }
635             std::vector<std::unique_ptr<C2SettingResult>> failures;
636             mIntf->config_vb(configUpdate, C2_MAY_BLOCK, &failures);
637 
638             std::shared_ptr<C2StreamHdrStaticInfo::input> hdrStaticInfo =
639                 mIntf->getHdrStaticMetadata();
640             uint32_t dataspace = mIntf->getDataSpace();
641 
642             std::shared_ptr<C2Buffer> buffer;
643             if (!work->input.buffers.empty()) {
644                 buffer = work->input.buffers.front();
645             }
646             std::shared_ptr<C2Buffer> outC2Buffer;
647             status_t err = OK;
648             if (buffer) {
649                 if (buffer->hasInfo(C2StreamHdrStaticInfo::output::PARAM_TYPE)) {
650                     std::shared_ptr<const C2Info> info =
651                         buffer->getInfo(C2StreamHdrStaticInfo::output::PARAM_TYPE);
652                     std::unique_ptr<C2Param> flipped = C2Param::CopyAsStream(
653                             *info, false /* output */, info->stream());
654                     hdrStaticInfo.reset(static_cast<C2StreamHdrStaticInfo::input *>(
655                             flipped.release()));
656                 }
657                 const C2Handle *c2Handle =
658                     buffer->data().graphicBlocks().front().handle();
659                 uint32_t width, height, format, stride, igbp_slot, generation;
660                 uint64_t usage, igbp_id;
661                 _UnwrapNativeCodec2GrallocMetadata(
662                         c2Handle, &width, &height, &format, &usage, &stride, &generation,
663                         &igbp_id, &igbp_slot);
664                 native_handle_t *grallocHandle = UnwrapNativeCodec2GrallocHandle(c2Handle);
665                 sp<GraphicBuffer> srcBuffer = new GraphicBuffer(
666                         grallocHandle, GraphicBuffer::CLONE_HANDLE,
667                         width, height, format, 1, usage, stride);
668 
669                 native_handle_delete(grallocHandle);
670                 std::shared_ptr<C2GraphicBlock> dstBlock;
671                 C2BlockPool::local_id_t poolId = mIntf->getPoolId();
672                 std::shared_ptr<C2BlockPool> pool;
673                 GetCodec2BlockPool(poolId, thiz, &pool);
674                 pool->fetchGraphicBlock(
675                         width, height, HAL_PIXEL_FORMAT_RGBA_8888, C2AndroidMemoryUsage::FromGrallocUsage(kDstUsage),
676                         &dstBlock);
677                 outC2Buffer = C2Buffer::CreateGraphicBuffer(
678                         dstBlock->share(C2Rect(width, height), C2Fence()));
679                 c2Handle = dstBlock->handle();
680                 _UnwrapNativeCodec2GrallocMetadata(
681                         c2Handle, &width, &height, &format, &usage, &stride, &generation,
682                         &igbp_id, &igbp_slot);
683                 grallocHandle = UnwrapNativeCodec2GrallocHandle(c2Handle);
684                 sp<GraphicBuffer> dstBuffer = new GraphicBuffer(
685                         grallocHandle, GraphicBuffer::CLONE_HANDLE,
686                         width, height, format, 1, usage, stride);
687 
688                 native_handle_delete(grallocHandle);
689                 Rect sourceCrop(0, 0, width, height);
690 
691                 renderengine::DisplaySettings clientCompositionDisplay;
692                 std::vector<const renderengine::LayerSettings*> clientCompositionLayers;
693 
694                 clientCompositionDisplay.physicalDisplay = sourceCrop;
695                 clientCompositionDisplay.clip = sourceCrop;
696 
697                 clientCompositionDisplay.outputDataspace = ui::Dataspace::V0_SRGB;
698                 clientCompositionDisplay.maxLuminance = kDefaultMaxLumiance;
699                 clientCompositionDisplay.clearRegion = Region::INVALID_REGION;
700                 renderengine::LayerSettings layerSettings;
701                 layerSettings.geometry.boundaries = sourceCrop.toFloatRect();
702                 layerSettings.alpha = 1.0f;
703 
704                 layerSettings.sourceDataspace = static_cast<ui::Dataspace>(dataspace);
705 
706                 // from BufferLayer
707                 layerSettings.source.buffer.buffer = srcBuffer;
708                 layerSettings.source.buffer.isOpaque = true;
709                 // TODO: fence
710                 layerSettings.source.buffer.fence = Fence::NO_FENCE;
711                 layerSettings.source.buffer.textureName = textureName;
712                 layerSettings.source.buffer.usePremultipliedAlpha = false;
713                 layerSettings.source.buffer.maxMasteringLuminance =
714                     (hdrStaticInfo && *hdrStaticInfo &&
715                      hdrStaticInfo->mastering.maxLuminance > 0 &&
716                      hdrStaticInfo->mastering.minLuminance > 0)
717                         ? hdrStaticInfo->mastering.maxLuminance : kDefaultMaxMasteringLuminance;
718                 layerSettings.source.buffer.maxContentLuminance =
719                     (hdrStaticInfo && *hdrStaticInfo && hdrStaticInfo->maxCll > 0)
720                         ? hdrStaticInfo->maxCll : kDefaultMaxContentLuminance;
721 
722                 // Set filtering to false since the capture itself doesn't involve
723                 // any scaling, metadata retriever JNI is scaling the bitmap if
724                 // display size is different from decoded size. If that scaling
725                 // needs to be handled by server side, consider enable this based
726                 // display size vs decoded size.
727                 layerSettings.source.buffer.useTextureFiltering = false;
728                 layerSettings.source.buffer.textureTransform = mat4();
729                 clientCompositionLayers.push_back(&layerSettings);
730 
731                 // Use an empty fence for the buffer fence, since we just created the buffer so
732                 // there is no need for synchronization with the GPU.
733                 base::unique_fd bufferFence;
734                 base::unique_fd drawFence;
735                 renderEngine->useProtectedContext(false);
736                 err = renderEngine->drawLayers(
737                         clientCompositionDisplay, clientCompositionLayers, dstBuffer.get(),
738                         /*useFramebufferCache=*/false, std::move(bufferFence), &drawFence);
739 
740                 sp<Fence> fence = new Fence(std::move(drawFence));
741 
742                 // We can move waiting for fence & sending it back on a separate thread to improve
743                 // efficiency, but leaving it here for simplicity.
744                 if (err != OK) {
745                     LOG(ERROR) << "drawLayers returned err " << err;
746                 } else {
747                     err = fence->wait(500);
748                     if (err != OK) {
749                         LOG(WARNING) << "wait for fence returned err " << err;
750                     }
751                 }
752                 renderEngine->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL);
753             }
754 
755             work->worklets.front()->output.ordinal = work->input.ordinal;
756             work->worklets.front()->output.flags = work->input.flags;
757             if (err == OK) {
758                 work->workletsProcessed = 1;
759                 if (outC2Buffer) {
760                     work->worklets.front()->output.buffers.push_back(outC2Buffer);
761                 }
762                 work->result = C2_OK;
763             } else {
764                 work->result = C2_CORRUPTED;
765             }
766             std::list<std::unique_ptr<C2Work>> items;
767             items.push_back(std::move(work));
768 
769             std::unique_lock lock(mListenerMutex);
770             mListener->onWorkDone_nb(thiz, std::move(items));
771             LOG(VERBOSE) << "sent work #" << workCount;
772         }
773     }
774 
775     mutable std::timed_mutex mListenerMutex;
776     std::shared_ptr<Listener> mListener;
777 
778     mutable std::mutex mQueueMutex;
779     mutable std::condition_variable mQueueCondition;
780     std::list<std::unique_ptr<C2Work>> mQueue;
781 
782     const std::shared_ptr<Interface> mIntf;
783 
784     mutable std::mutex mStateMutex;
785     enum State {
786         STOPPED,
787         RUNNING,
788         RELEASED,
789         STARTING,   // STOPPED -> RUNNING
790         STOPPING,   // RUNNING -> STOPPED
791         RESETTING,  // <<ANY>> -> STOPPED
792         RELEASING,  // STOPPED -> RELEASED
793     } mState;
794 
795     mutable std::mutex mProcessingMutex;
796     std::thread mProcessingThread;
797 
798 };
799 
800 // static
801 const std::string SampleToneMappingFilter::Interface::NAME = "c2.sample.tone-mapper";
802 // static
803 const FilterPlugin_V1::Descriptor SampleToneMappingFilter::Interface::DESCRIPTOR = {
804     // controlParams
805     { C2StreamColorAspectsRequestInfo::output::PARAM_TYPE },
806     // affectedParams
807     {
808         C2StreamHdrStaticInfo::output::PARAM_TYPE,
809         C2StreamColorAspectsInfo::output::PARAM_TYPE,
810     },
811 };
812 
813 class SampleC2ComponentStore : public C2ComponentStore {
814 public:
SampleC2ComponentStore()815     SampleC2ComponentStore()
816         : mReflector(std::make_shared<C2ReflectorHelper>()),
817           mIntf(mReflector),
818           mFactories(CreateFactories()) {
819     }
820     ~SampleC2ComponentStore() = default;
821 
getName() const822     C2String getName() const override { return "android.sample.filter-plugin-store"; }
createComponent(C2String name,std::shared_ptr<C2Component> * const component)823     c2_status_t createComponent(
824             C2String name, std::shared_ptr<C2Component>* const component) override {
825         if (mFactories.count(name) == 0) {
826             return C2_BAD_VALUE;
827         }
828         return mFactories.at(name)->createComponent(++mNodeId, component);
829     }
createInterface(C2String name,std::shared_ptr<C2ComponentInterface> * const interface)830     c2_status_t createInterface(
831             C2String name, std::shared_ptr<C2ComponentInterface>* const interface) override {
832         if (mFactories.count(name) == 0) {
833             return C2_BAD_VALUE;
834         }
835         return mFactories.at(name)->createInterface(++mNodeId, interface);
836     }
listComponents()837     std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override {
838         std::vector<std::shared_ptr<const C2Component::Traits>> ret;
839         for (const auto &[name, factory] : mFactories) {
840             ret.push_back(factory->getTraits());
841         }
842         return ret;
843     }
copyBuffer(std::shared_ptr<C2GraphicBuffer>,std::shared_ptr<C2GraphicBuffer>)844     c2_status_t copyBuffer(
845             std::shared_ptr<C2GraphicBuffer>, std::shared_ptr<C2GraphicBuffer>) override {
846         return C2_OMITTED;
847     }
query_sm(const std::vector<C2Param * > & stackParams,const std::vector<C2Param::Index> & heapParamIndices,std::vector<std::unique_ptr<C2Param>> * const heapParams) const848     c2_status_t query_sm(
849             const std::vector<C2Param*> &stackParams,
850             const std::vector<C2Param::Index> &heapParamIndices,
851             std::vector<std::unique_ptr<C2Param>>* const heapParams) const override {
852         return mIntf.query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
853     }
config_sm(const std::vector<C2Param * > & params,std::vector<std::unique_ptr<C2SettingResult>> * const failures)854     c2_status_t config_sm(
855             const std::vector<C2Param*> &params,
856             std::vector<std::unique_ptr<C2SettingResult>>* const failures) override {
857         return mIntf.config(params, C2_MAY_BLOCK, failures);
858     }
getParamReflector() const859     std::shared_ptr<C2ParamReflector> getParamReflector() const override {
860         return mReflector;
861     }
querySupportedParams_nb(std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const862     c2_status_t querySupportedParams_nb(
863             std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const override {
864         return mIntf.querySupportedParams(params);
865     }
querySupportedValues_sm(std::vector<C2FieldSupportedValuesQuery> & fields) const866     c2_status_t querySupportedValues_sm(
867             std::vector<C2FieldSupportedValuesQuery> &fields) const override {
868         return mIntf.querySupportedValues(fields, C2_MAY_BLOCK);
869     }
870 
871 private:
872     class ComponentFactory {
873     public:
874         virtual ~ComponentFactory() = default;
875 
getTraits()876         const std::shared_ptr<const C2Component::Traits> &getTraits() { return mTraits; }
877 
878         virtual c2_status_t createComponent(
879                 c2_node_id_t id,
880                 std::shared_ptr<C2Component>* const component) const = 0;
881         virtual c2_status_t createInterface(
882                 c2_node_id_t id,
883                 std::shared_ptr<C2ComponentInterface>* const interface) const = 0;
884     protected:
ComponentFactory(const std::shared_ptr<const C2Component::Traits> & traits)885         ComponentFactory(const std::shared_ptr<const C2Component::Traits> &traits)
886             : mTraits(traits) {
887         }
888     private:
889         const std::shared_ptr<const C2Component::Traits> mTraits;
890     };
891 
892     template <class T>
893     struct ComponentFactoryImpl : public ComponentFactory {
894     public:
ComponentFactoryImplandroid::SampleC2ComponentStore::ComponentFactoryImpl895         ComponentFactoryImpl(const std::shared_ptr<const C2Component::Traits> &traits)
896             : ComponentFactory(traits) {
897         }
898         ~ComponentFactoryImpl() override = default;
createComponentandroid::SampleC2ComponentStore::ComponentFactoryImpl899         c2_status_t createComponent(
900                 c2_node_id_t id,
901                 std::shared_ptr<C2Component>* const component) const override {
902             *component = std::make_shared<T>(id);
903             return C2_OK;
904         }
createInterfaceandroid::SampleC2ComponentStore::ComponentFactoryImpl905         c2_status_t createInterface(
906                 c2_node_id_t id,
907                 std::shared_ptr<C2ComponentInterface>* const interface) const override {
908             *interface = std::make_shared<typename T::Interface>(id);
909             return C2_OK;
910         }
911     };
912 
913     template <class T>
AddFactory(std::map<C2String,std::unique_ptr<ComponentFactory>> * factories)914     static void AddFactory(std::map<C2String, std::unique_ptr<ComponentFactory>> *factories) {
915         std::shared_ptr<C2ComponentInterface> intf{new typename T::Interface(0)};
916         std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
917         CHECK(C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf))
918                 << "Failed to fill traits from interface";
919         factories->emplace(traits->name, new ComponentFactoryImpl<T>(traits));
920     }
921 
CreateFactories()922     static std::map<C2String, std::unique_ptr<ComponentFactory>> CreateFactories() {
923         std::map<C2String, std::unique_ptr<ComponentFactory>> factories;
924         AddFactory<SampleToneMappingFilter>(&factories);
925         return factories;
926     }
927 
928 
929     std::shared_ptr<C2ReflectorHelper> mReflector;
930     struct Interface : public C2InterfaceHelper {
Interfaceandroid::SampleC2ComponentStore::Interface931         explicit Interface(std::shared_ptr<C2ReflectorHelper> reflector)
932             : C2InterfaceHelper(reflector) {
933         }
934     } mIntf;
935 
936     const std::map<C2String, std::unique_ptr<ComponentFactory>> mFactories;
937 
938     std::atomic_int32_t mNodeId{0};
939 };
940 
941 class SampleFilterPlugin : public FilterPlugin_V1 {
942 public:
SampleFilterPlugin()943     SampleFilterPlugin() : mStore(new SampleC2ComponentStore) {}
944     ~SampleFilterPlugin() override = default;
945 
getComponentStore()946     std::shared_ptr<C2ComponentStore> getComponentStore() override {
947         return mStore;
948     }
949 
describe(C2String name,Descriptor * desc)950     bool describe(C2String name, Descriptor *desc) override {
951         if (name == SampleToneMappingFilter::Interface::NAME) {
952             *desc = SampleToneMappingFilter::Interface::DESCRIPTOR;
953             return true;
954         }
955         return false;
956     }
957 
isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> & intf)958     bool isFilteringEnabled(const std::shared_ptr<C2ComponentInterface> &intf) override {
959         if (intf->getName() == SampleToneMappingFilter::Interface::NAME) {
960             return SampleToneMappingFilter::Interface::IsFilteringEnabled(intf);
961         }
962         return false;
963     }
964 
queryParamsForPreviousComponent(const std::shared_ptr<C2ComponentInterface> & intf,std::vector<std::unique_ptr<C2Param>> * params)965     c2_status_t queryParamsForPreviousComponent(
966             const std::shared_ptr<C2ComponentInterface> &intf,
967             std::vector<std::unique_ptr<C2Param>> *params) override {
968         if (intf->getName() == SampleToneMappingFilter::Interface::NAME) {
969             return SampleToneMappingFilter::Interface::QueryParamsForPreviousComponent(
970                     intf, params);
971         }
972         return C2_BAD_VALUE;
973     }
974 
975 private:
976     std::shared_ptr<C2ComponentStore> mStore;
977 };
978 
979 }  // namespace android
980 
981 extern "C" {
982 
GetFilterPluginVersion()983 int32_t GetFilterPluginVersion() {
984     return ::android::SampleFilterPlugin::VERSION;
985 }
986 
CreateFilterPlugin()987 void *CreateFilterPlugin() {
988     return new ::android::SampleFilterPlugin;
989 }
990 
DestroyFilterPlugin(void * plugin)991 void DestroyFilterPlugin(void *plugin) {
992     delete (::android::SampleFilterPlugin *)plugin;
993 }
994 
995 }  // extern "C"
996