1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "C2GoldfishVpxDec"
19 #include <log/log.h>
20 
21 #include <algorithm>
22 
23 #include <media/stagefright/foundation/AUtils.h>
24 #include <media/stagefright/foundation/MediaDefs.h>
25 
26 #include <C2AllocatorGralloc.h>
27 #include <C2PlatformSupport.h>
28 //#include <android/hardware/graphics/common/1.0/types.h>
29 
30 #include <android/hardware/graphics/allocator/3.0/IAllocator.h>
31 #include <android/hardware/graphics/mapper/3.0/IMapper.h>
32 #include <hidl/LegacySupport.h>
33 
34 #include <C2Debug.h>
35 #include <C2PlatformSupport.h>
36 #include <SimpleC2Interface.h>
37 #include <goldfish_codec2/store/GoldfishComponentStore.h>
38 
39 #include <gralloc_cb_bp.h>
40 
41 #include <color_buffer_utils.h>
42 
43 #include "C2GoldfishVpxDec.h"
44 
45 #define DEBUG 0
46 #if DEBUG
47 #define DDD(...) ALOGW(__VA_ARGS__)
48 #else
49 #define DDD(...) ((void)0)
50 #endif
51 using ::android::hardware::graphics::common::V1_0::BufferUsage;
52 using ::android::hardware::graphics::common::V1_2::PixelFormat;
53 
54 namespace android {
55 constexpr size_t kMinInputBufferSize = 6 * 1024 * 1024;
56 #ifdef VP9
57 constexpr char COMPONENT_NAME[] = "c2.goldfish.vp9.decoder";
58 #else
59 constexpr char COMPONENT_NAME[] = "c2.goldfish.vp8.decoder";
60 #endif
61 
62 class C2GoldfishVpxDec::IntfImpl : public SimpleInterface<void>::BaseParams {
63   public:
IntfImpl(const std::shared_ptr<C2ReflectorHelper> & helper)64     explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
65         : SimpleInterface<void>::BaseParams(helper, COMPONENT_NAME,
66                                             C2Component::KIND_DECODER,
67                                             C2Component::DOMAIN_VIDEO,
68 #ifdef VP9
69                                             MEDIA_MIMETYPE_VIDEO_VP9
70 #else
71                                             MEDIA_MIMETYPE_VIDEO_VP8
72 #endif
73           ) {
74         DDD("calling IntfImpl now helper %p", helper.get());
75         noPrivateBuffers(); // TODO: account for our buffers here
76         noInputReferences();
77         noOutputReferences();
78         noInputLatency();
79         noTimeStretch();
80 
81         // TODO: output latency and reordering
82 
83         addParameter(DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
84                          .withConstValue(new C2ComponentAttributesSetting(
85                              C2Component::ATTRIB_IS_TEMPORAL))
86                          .build());
87 
88         addParameter(
89             DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
90                 .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
91                 .withFields({
92                     C2F(mSize, width).inRange(2, 4096, 2),
93                     C2F(mSize, height).inRange(2, 4096, 2),
94                 })
95                 .withSetter(SizeSetter)
96                 .build());
97 
98 #ifdef VP9
99         // TODO: Add C2Config::PROFILE_VP9_2HDR ??
100         addParameter(
101             DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
102                 .withDefault(new C2StreamProfileLevelInfo::input(
103                     0u, C2Config::PROFILE_VP9_0, C2Config::LEVEL_VP9_5))
104                 .withFields({C2F(mProfileLevel, profile)
105                                  .oneOf({C2Config::PROFILE_VP9_0,
106                                          C2Config::PROFILE_VP9_2}),
107                              C2F(mProfileLevel, level)
108                                  .oneOf({
109                                      C2Config::LEVEL_VP9_1,
110                                      C2Config::LEVEL_VP9_1_1,
111                                      C2Config::LEVEL_VP9_2,
112                                      C2Config::LEVEL_VP9_2_1,
113                                      C2Config::LEVEL_VP9_3,
114                                      C2Config::LEVEL_VP9_3_1,
115                                      C2Config::LEVEL_VP9_4,
116                                      C2Config::LEVEL_VP9_4_1,
117                                      C2Config::LEVEL_VP9_5,
118                                  })})
119                 .withSetter(ProfileLevelSetter, mSize)
120                 .build());
121 
122         mHdr10PlusInfoInput = C2StreamHdr10PlusInfo::input::AllocShared(0);
123         addParameter(
124             DefineParam(mHdr10PlusInfoInput, C2_PARAMKEY_INPUT_HDR10_PLUS_INFO)
125                 .withDefault(mHdr10PlusInfoInput)
126                 .withFields({
127                     C2F(mHdr10PlusInfoInput, m.value).any(),
128                 })
129                 .withSetter(Hdr10PlusInfoInputSetter)
130                 .build());
131 
132         mHdr10PlusInfoOutput = C2StreamHdr10PlusInfo::output::AllocShared(0);
133         addParameter(DefineParam(mHdr10PlusInfoOutput,
134                                  C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO)
135                          .withDefault(mHdr10PlusInfoOutput)
136                          .withFields({
137                              C2F(mHdr10PlusInfoOutput, m.value).any(),
138                          })
139                          .withSetter(Hdr10PlusInfoOutputSetter)
140                          .build());
141 
142 #if 0
143         // sample BT.2020 static info
144         mHdrStaticInfo = std::make_shared<C2StreamHdrStaticInfo::output>();
145         mHdrStaticInfo->mastering = {
146             .red   = { .x = 0.708,  .y = 0.292 },
147             .green = { .x = 0.170,  .y = 0.797 },
148             .blue  = { .x = 0.131,  .y = 0.046 },
149             .white = { .x = 0.3127, .y = 0.3290 },
150             .maxLuminance = 1000,
151             .minLuminance = 0.1,
152         };
153         mHdrStaticInfo->maxCll = 1000;
154         mHdrStaticInfo->maxFall = 120;
155 
156         mHdrStaticInfo->maxLuminance = 0; // disable static info
157 
158         helper->addStructDescriptors<C2MasteringDisplayColorVolumeStruct, C2ColorXyStruct>();
159         addParameter(
160                 DefineParam(mHdrStaticInfo, C2_PARAMKEY_HDR_STATIC_INFO)
161                 .withDefault(mHdrStaticInfo)
162                 .withFields({
163                     C2F(mHdrStaticInfo, mastering.red.x).inRange(0, 1),
164                     // TODO
165                 })
166                 .withSetter(HdrStaticInfoSetter)
167                 .build());
168 #endif
169 #else
170         addParameter(
171             DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
172                 .withConstValue(new C2StreamProfileLevelInfo::input(
173                     0u, C2Config::PROFILE_UNUSED, C2Config::LEVEL_UNUSED))
174                 .build());
175 #endif
176 
177         addParameter(DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
178                          .withDefault(new C2StreamMaxPictureSizeTuning::output(
179                              0u, 320, 240))
180                          .withFields({
181                              C2F(mSize, width).inRange(2, 4096, 2),
182                              C2F(mSize, height).inRange(2, 4096, 2),
183                          })
184                          .withSetter(MaxPictureSizeSetter, mSize)
185                          .build());
186 
187         addParameter(
188             DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
189                 .withDefault(new C2StreamMaxBufferSizeInfo::input(
190                     0u, kMinInputBufferSize))
191                 .withFields({
192                     C2F(mMaxInputSize, value).any(),
193                 })
194                 .calculatedAs(MaxInputSizeSetter, mMaxSize)
195                 .build());
196 
197         C2ChromaOffsetStruct locations[1] = {
198             C2ChromaOffsetStruct::ITU_YUV_420_0()};
199         std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
200             C2StreamColorInfo::output::AllocShared(1u, 0u, 8u /* bitDepth */,
201                                                    C2Color::YUV_420);
202         memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
203 
204         defaultColorInfo = C2StreamColorInfo::output::AllocShared(
205             {C2ChromaOffsetStruct::ITU_YUV_420_0()}, 0u, 8u /* bitDepth */,
206             C2Color::YUV_420);
207         helper->addStructDescriptors<C2ChromaOffsetStruct>();
208 
209         addParameter(DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
210                          .withConstValue(defaultColorInfo)
211                          .build());
212 
213         addParameter(
214             DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
215                 .withDefault(new C2StreamColorAspectsTuning::output(
216                     0u, C2Color::RANGE_UNSPECIFIED,
217                     C2Color::PRIMARIES_UNSPECIFIED,
218                     C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
219                 .withFields({C2F(mDefaultColorAspects, range)
220                                  .inRange(C2Color::RANGE_UNSPECIFIED,
221                                           C2Color::RANGE_OTHER),
222                              C2F(mDefaultColorAspects, primaries)
223                                  .inRange(C2Color::PRIMARIES_UNSPECIFIED,
224                                           C2Color::PRIMARIES_OTHER),
225                              C2F(mDefaultColorAspects, transfer)
226                                  .inRange(C2Color::TRANSFER_UNSPECIFIED,
227                                           C2Color::TRANSFER_OTHER),
228                              C2F(mDefaultColorAspects, matrix)
229                                  .inRange(C2Color::MATRIX_UNSPECIFIED,
230                                           C2Color::MATRIX_OTHER)})
231                 .withSetter(DefaultColorAspectsSetter)
232                 .build());
233 
234         addParameter(
235             DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
236                 .withDefault(new C2StreamColorAspectsInfo::input(
237                     0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
238                     C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
239                 .withFields({C2F(mCodedColorAspects, range)
240                                  .inRange(C2Color::RANGE_UNSPECIFIED,
241                                           C2Color::RANGE_OTHER),
242                              C2F(mCodedColorAspects, primaries)
243                                  .inRange(C2Color::PRIMARIES_UNSPECIFIED,
244                                           C2Color::PRIMARIES_OTHER),
245                              C2F(mCodedColorAspects, transfer)
246                                  .inRange(C2Color::TRANSFER_UNSPECIFIED,
247                                           C2Color::TRANSFER_OTHER),
248                              C2F(mCodedColorAspects, matrix)
249                                  .inRange(C2Color::MATRIX_UNSPECIFIED,
250                                           C2Color::MATRIX_OTHER)})
251                 .withSetter(CodedColorAspectsSetter)
252                 .build());
253 
254         addParameter(
255             DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
256                 .withDefault(new C2StreamColorAspectsInfo::output(
257                     0u, C2Color::RANGE_UNSPECIFIED,
258                     C2Color::PRIMARIES_UNSPECIFIED,
259                     C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
260                 .withFields({C2F(mColorAspects, range)
261                                  .inRange(C2Color::RANGE_UNSPECIFIED,
262                                           C2Color::RANGE_OTHER),
263                              C2F(mColorAspects, primaries)
264                                  .inRange(C2Color::PRIMARIES_UNSPECIFIED,
265                                           C2Color::PRIMARIES_OTHER),
266                              C2F(mColorAspects, transfer)
267                                  .inRange(C2Color::TRANSFER_UNSPECIFIED,
268                                           C2Color::TRANSFER_OTHER),
269                              C2F(mColorAspects, matrix)
270                                  .inRange(C2Color::MATRIX_UNSPECIFIED,
271                                           C2Color::MATRIX_OTHER)})
272                 .withSetter(ColorAspectsSetter, mDefaultColorAspects,
273                             mCodedColorAspects)
274                 .build());
275 
276         // TODO: support more formats?
277         addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
278                          .withConstValue(new C2StreamPixelFormatInfo::output(
279                              0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
280                          .build());
281     }
282 
SizeSetter(bool mayBlock,const C2P<C2StreamPictureSizeInfo::output> & oldMe,C2P<C2StreamPictureSizeInfo::output> & me)283     static C2R SizeSetter(bool mayBlock,
284                           const C2P<C2StreamPictureSizeInfo::output> &oldMe,
285                           C2P<C2StreamPictureSizeInfo::output> &me) {
286         (void)mayBlock;
287         DDD("calling sizesetter old w %d", oldMe.v.width);
288         DDD("calling sizesetter old h %d", oldMe.v.height);
289         DDD("calling sizesetter change to w %d", me.v.width);
290         DDD("calling sizesetter change to h %d", me.v.height);
291         C2R res = C2R::Ok();
292         auto mewidth = me.F(me.v.width);
293         auto meheight = me.F(me.v.height);
294 
295         if (!mewidth.supportsAtAll(me.v.width)) {
296             res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
297             DDD("override width with oldMe value");
298             me.set().width = oldMe.v.width;
299             DDD("something wrong here %s %d", __func__, __LINE__);
300         }
301         if (!meheight.supportsAtAll(me.v.height)) {
302             res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
303             DDD("override height with oldMe value");
304             me.set().height = oldMe.v.height;
305             DDD("something wrong here %s %d", __func__, __LINE__);
306         }
307         return res;
308     }
309 
310     static C2R
MaxPictureSizeSetter(bool mayBlock,C2P<C2StreamMaxPictureSizeTuning::output> & me,const C2P<C2StreamPictureSizeInfo::output> & size)311     MaxPictureSizeSetter(bool mayBlock,
312                          C2P<C2StreamMaxPictureSizeTuning::output> &me,
313                          const C2P<C2StreamPictureSizeInfo::output> &size) {
314         (void)mayBlock;
315         // TODO: get max width/height from the size's field helpers vs.
316         // hardcoding
317         me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4096u);
318         me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4096u);
319         return C2R::Ok();
320     }
321 
MaxInputSizeSetter(bool mayBlock,C2P<C2StreamMaxBufferSizeInfo::input> & me,const C2P<C2StreamMaxPictureSizeTuning::output> & maxSize)322     static C2R MaxInputSizeSetter(
323         bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me,
324         const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
325         (void)mayBlock;
326         // assume compression ratio of 2
327         me.set().value = c2_max((((maxSize.v.width + 63) / 64) *
328                                  ((maxSize.v.height + 63) / 64) * 3072),
329                                 kMinInputBufferSize);
330         return C2R::Ok();
331     }
332 
333     static C2R
DefaultColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsTuning::output> & me)334     DefaultColorAspectsSetter(bool mayBlock,
335                               C2P<C2StreamColorAspectsTuning::output> &me) {
336         (void)mayBlock;
337         if (me.v.range > C2Color::RANGE_OTHER) {
338             me.set().range = C2Color::RANGE_OTHER;
339         }
340         if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
341             me.set().primaries = C2Color::PRIMARIES_OTHER;
342         }
343         if (me.v.transfer > C2Color::TRANSFER_OTHER) {
344             me.set().transfer = C2Color::TRANSFER_OTHER;
345         }
346         if (me.v.matrix > C2Color::MATRIX_OTHER) {
347             me.set().matrix = C2Color::MATRIX_OTHER;
348         }
349         DDD("%s %d update range %d primaries/color %d transfer %d",
350                 __func__, __LINE__,
351                 (int)(me.v.range),
352                 (int)(me.v.primaries),
353                 (int)(me.v.transfer)
354                 );
355         return C2R::Ok();
356     }
357 
358     static C2R
CodedColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsInfo::input> & me)359     CodedColorAspectsSetter(bool mayBlock,
360                             C2P<C2StreamColorAspectsInfo::input> &me) {
361         (void)mayBlock;
362         if (me.v.range > C2Color::RANGE_OTHER) {
363             me.set().range = C2Color::RANGE_OTHER;
364         }
365         if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
366             me.set().primaries = C2Color::PRIMARIES_OTHER;
367         }
368         if (me.v.transfer > C2Color::TRANSFER_OTHER) {
369             me.set().transfer = C2Color::TRANSFER_OTHER;
370         }
371         if (me.v.matrix > C2Color::MATRIX_OTHER) {
372             me.set().matrix = C2Color::MATRIX_OTHER;
373         }
374         DDD("%s %d coded color aspect range %d primaries/color %d transfer %d",
375                 __func__, __LINE__,
376                 (int)(me.v.range),
377                 (int)(me.v.primaries),
378                 (int)(me.v.transfer)
379                 );
380         return C2R::Ok();
381     }
382 
383     static C2R
ColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsInfo::output> & me,const C2P<C2StreamColorAspectsTuning::output> & def,const C2P<C2StreamColorAspectsInfo::input> & coded)384     ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
385                        const C2P<C2StreamColorAspectsTuning::output> &def,
386                        const C2P<C2StreamColorAspectsInfo::input> &coded) {
387         (void)mayBlock;
388         // take default values for all unspecified fields, and coded values for
389         // specified ones
390         DDD("%s %d before update: color aspect range %d primaries/color %d transfer %d",
391                 __func__, __LINE__,
392                 (int)(me.v.range),
393                 (int)(me.v.primaries),
394                 (int)(me.v.transfer)
395                 );
396         me.set().range =
397             coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range;
398         me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED
399                                  ? def.v.primaries
400                                  : coded.v.primaries;
401         me.set().transfer = coded.v.transfer == TRANSFER_UNSPECIFIED
402                                 ? def.v.transfer
403                                 : coded.v.transfer;
404         me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix
405                                                                : coded.v.matrix;
406 
407         DDD("%s %d after update: color aspect range %d primaries/color %d transfer %d",
408                 __func__, __LINE__,
409                 (int)(me.v.range),
410                 (int)(me.v.primaries),
411                 (int)(me.v.transfer)
412                 );
413         return C2R::Ok();
414     }
415 
416     static C2R
ProfileLevelSetter(bool mayBlock,C2P<C2StreamProfileLevelInfo::input> & me,const C2P<C2StreamPictureSizeInfo::output> & size)417     ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
418                        const C2P<C2StreamPictureSizeInfo::output> &size) {
419         (void)mayBlock;
420         (void)size;
421         (void)me; // TODO: validate
422         return C2R::Ok();
423     }
424     std::shared_ptr<C2StreamColorAspectsTuning::output>
getDefaultColorAspects_l()425     getDefaultColorAspects_l() {
426         return mDefaultColorAspects;
427     }
428 
getColorAspects_l()429     std::shared_ptr<C2StreamColorAspectsInfo::output> getColorAspects_l() {
430         return mColorAspects;
431     }
432 
width() const433     int width() const { return mSize->width; }
434 
height() const435     int height() const { return mSize->height; }
436 
primaries() const437     int primaries() const { return mDefaultColorAspects->primaries; }
438 
range() const439     int range() const { return mDefaultColorAspects->range; }
440 
transfer() const441     int transfer() const { return mDefaultColorAspects->transfer; }
442 
Hdr10PlusInfoInputSetter(bool mayBlock,C2P<C2StreamHdr10PlusInfo::input> & me)443     static C2R Hdr10PlusInfoInputSetter(bool mayBlock,
444                                         C2P<C2StreamHdr10PlusInfo::input> &me) {
445         (void)mayBlock;
446         (void)me; // TODO: validate
447         return C2R::Ok();
448     }
449 
450     static C2R
Hdr10PlusInfoOutputSetter(bool mayBlock,C2P<C2StreamHdr10PlusInfo::output> & me)451     Hdr10PlusInfoOutputSetter(bool mayBlock,
452                               C2P<C2StreamHdr10PlusInfo::output> &me) {
453         (void)mayBlock;
454         (void)me; // TODO: validate
455         return C2R::Ok();
456     }
457 
458   private:
459     std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
460     std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
461     std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize;
462     std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize;
463     std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
464     std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
465     std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
466     std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects;
467     std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
468 #ifdef VP9
469 #if 0
470     std::shared_ptr<C2StreamHdrStaticInfo::output> mHdrStaticInfo;
471 #endif
472     std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput;
473     std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput;
474 #endif
475 };
476 
ConverterThread(const std::shared_ptr<Mutexed<ConversionQueue>> & queue)477 C2GoldfishVpxDec::ConverterThread::ConverterThread(
478     const std::shared_ptr<Mutexed<ConversionQueue>> &queue)
479     : Thread(false), mQueue(queue) {}
480 
threadLoop()481 bool C2GoldfishVpxDec::ConverterThread::threadLoop() {
482     Mutexed<ConversionQueue>::Locked queue(*mQueue);
483     if (queue->entries.empty()) {
484         queue.waitForCondition(queue->cond);
485         if (queue->entries.empty()) {
486             return true;
487         }
488     }
489     std::function<void()> convert = queue->entries.front();
490     queue->entries.pop_front();
491     if (!queue->entries.empty()) {
492         queue->cond.signal();
493     }
494     queue.unlock();
495 
496     convert();
497 
498     queue.lock();
499     if (--queue->numPending == 0u) {
500         queue->cond.broadcast();
501     }
502     return true;
503 }
504 
C2GoldfishVpxDec(const char * name,c2_node_id_t id,const std::shared_ptr<IntfImpl> & intfImpl)505 C2GoldfishVpxDec::C2GoldfishVpxDec(const char *name, c2_node_id_t id,
506                                    const std::shared_ptr<IntfImpl> &intfImpl)
507     : SimpleC2Component(
508           std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
509       mIntf(intfImpl), mCtx(nullptr), mQueue(new Mutexed<ConversionQueue>) {}
510 
~C2GoldfishVpxDec()511 C2GoldfishVpxDec::~C2GoldfishVpxDec() { onRelease(); }
512 
onInit()513 c2_status_t C2GoldfishVpxDec::onInit() {
514     status_t err = initDecoder();
515     return err == OK ? C2_OK : C2_CORRUPTED;
516 }
517 
onStop()518 c2_status_t C2GoldfishVpxDec::onStop() {
519     mSignalledError = false;
520     mSignalledOutputEos = false;
521 
522     return C2_OK;
523 }
524 
onReset()525 void C2GoldfishVpxDec::onReset() {
526     (void)onStop();
527     c2_status_t err = onFlush_sm();
528     if (err != C2_OK) {
529         ALOGW("Failed to flush decoder. Try to hard reset decoder");
530         destroyDecoder();
531         (void)initDecoder();
532     }
533 }
534 
onRelease()535 void C2GoldfishVpxDec::onRelease() { destroyDecoder(); }
536 
sendMetadata()537 void C2GoldfishVpxDec::sendMetadata() {
538     // compare and send if changed
539     MetaDataColorAspects currentMetaData = {1, 0, 0, 0};
540     currentMetaData.primaries = mIntf->primaries();
541     currentMetaData.range = mIntf->range();
542     currentMetaData.transfer = mIntf->transfer();
543 
544     DDD("metadata primaries %d range %d transfer %d",
545             (int)(currentMetaData.primaries),
546             (int)(currentMetaData.range),
547             (int)(currentMetaData.transfer)
548        );
549 
550     if (mSentMetadata.primaries == currentMetaData.primaries &&
551         mSentMetadata.range == currentMetaData.range &&
552         mSentMetadata.transfer == currentMetaData.transfer) {
553         DDD("metadata is the same, no need to update");
554         return;
555     }
556     std::swap(mSentMetadata, currentMetaData);
557 
558     vpx_codec_send_metadata(mCtx, &(mSentMetadata));
559 }
560 
onFlush_sm()561 c2_status_t C2GoldfishVpxDec::onFlush_sm() {
562     if (mFrameParallelMode) {
563         // Flush decoder by passing nullptr data ptr and 0 size.
564         // Ideally, this should never fail.
565         if (vpx_codec_flush(mCtx)) {
566             ALOGE("Failed to flush on2 decoder.");
567             return C2_CORRUPTED;
568         }
569     }
570 
571     // Drop all the decoded frames in decoder.
572     if (mCtx) {
573         setup_ctx_parameters(mCtx);
574         while ((mImg = vpx_codec_get_frame(mCtx))) {
575         }
576     }
577 
578     mSignalledError = false;
579     mSignalledOutputEos = false;
580     return C2_OK;
581 }
582 
initDecoder()583 status_t C2GoldfishVpxDec::initDecoder() {
584     ALOGI("calling init GoldfishVPX");
585 #ifdef VP9
586     mMode = MODE_VP9;
587 #else
588     mMode = MODE_VP8;
589 #endif
590 
591     mWidth = 320;
592     mHeight = 240;
593     mFrameParallelMode = false;
594     mSignalledOutputEos = false;
595     mSignalledError = false;
596 
597     return OK;
598 }
599 
checkContext(const std::shared_ptr<C2BlockPool> & pool)600 void C2GoldfishVpxDec::checkContext(const std::shared_ptr<C2BlockPool> &pool) {
601     if (mCtx)
602         return;
603 
604     mWidth = mIntf->width();
605     mHeight = mIntf->height();
606     ALOGI("created decoder context w %d h %d", mWidth, mHeight);
607     mCtx = new vpx_codec_ctx_t;
608     mCtx->vpversion = mMode == MODE_VP8 ? 8 : 9;
609 
610     //const bool isGraphic = (pool->getLocalId() == C2PlatformAllocatorStore::GRALLOC);
611     const bool isGraphic = (pool->getAllocatorId() & C2Allocator::GRAPHIC);
612     DDD("buffer pool allocator id %x",  (int)(pool->getAllocatorId()));
613     if (isGraphic) {
614         uint64_t client_usage = getClientUsage(pool);
615         DDD("client has usage as 0x%llx", client_usage);
616         if (client_usage & BufferUsage::CPU_READ_MASK) {
617             DDD("decoding to guest byte buffer as client has read usage");
618             mEnableAndroidNativeBuffers = false;
619         } else {
620             DDD("decoding to host color buffer");
621             mEnableAndroidNativeBuffers = true;
622         }
623     } else {
624         DDD("decoding to guest byte buffer");
625         mEnableAndroidNativeBuffers = false;
626     }
627 
628     mCtx->version = mEnableAndroidNativeBuffers ? 200 : 100;
629 
630     int vpx_err = 0;
631     if ((vpx_err = vpx_codec_dec_init(mCtx))) {
632         ALOGE("vpx decoder failed to initialize. (%d)", vpx_err);
633         delete mCtx;
634         mCtx = NULL;
635     }
636 }
637 
destroyDecoder()638 status_t C2GoldfishVpxDec::destroyDecoder() {
639     if (mCtx) {
640         ALOGI("calling destroying GoldfishVPX ctx %p", mCtx);
641         vpx_codec_destroy(mCtx);
642         delete mCtx;
643         mCtx = NULL;
644     }
645 
646     return OK;
647 }
648 
fillEmptyWork(const std::unique_ptr<C2Work> & work)649 void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
650     uint32_t flags = 0;
651     if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
652         flags |= C2FrameData::FLAG_END_OF_STREAM;
653         DDD("signalling eos");
654     }
655     work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
656     work->worklets.front()->output.buffers.clear();
657     work->worklets.front()->output.ordinal = work->input.ordinal;
658     work->workletsProcessed = 1u;
659 }
660 
finishWork(uint64_t index,const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2GraphicBlock> & block)661 void C2GoldfishVpxDec::finishWork(
662     uint64_t index, const std::unique_ptr<C2Work> &work,
663     const std::shared_ptr<C2GraphicBlock> &block) {
664     std::shared_ptr<C2Buffer> buffer =
665         createGraphicBuffer(block, C2Rect(mWidth, mHeight));
666     {
667         IntfImpl::Lock lock = mIntf->lock();
668 #ifdef VP9
669         buffer->setInfo(mIntf->getColorAspects_l());
670 #else
671         std::shared_ptr<C2StreamColorAspectsInfo::output> tColorAspects =
672             std::make_shared<C2StreamColorAspectsInfo::output>
673             (C2StreamColorAspectsInfo::output(0u, m_range,
674                 m_primaries, m_transfer,
675                 m_matrix));
676         DDD("%s %d setting to index %d range %d primaries %d transfer %d",
677                 __func__, __LINE__, (int)index,
678                 (int)tColorAspects->range,
679                 (int)tColorAspects->primaries,
680                 (int)tColorAspects->transfer);
681         buffer->setInfo(tColorAspects);
682 #endif
683     }
684 
685     auto fillWork = [buffer, index,
686                      intf = this->mIntf](const std::unique_ptr<C2Work> &work) {
687         uint32_t flags = 0;
688         if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
689             (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
690             flags |= C2FrameData::FLAG_END_OF_STREAM;
691             DDD("signalling eos");
692         }
693         work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
694         work->worklets.front()->output.buffers.clear();
695         work->worklets.front()->output.buffers.push_back(buffer);
696         work->worklets.front()->output.ordinal = work->input.ordinal;
697         work->workletsProcessed = 1u;
698 
699         for (const std::unique_ptr<C2Param> &param : work->input.configUpdate) {
700             if (param) {
701                 C2StreamHdr10PlusInfo::input *hdr10PlusInfo =
702                     C2StreamHdr10PlusInfo::input::From(param.get());
703 
704                 if (hdr10PlusInfo != nullptr) {
705                     std::vector<std::unique_ptr<C2SettingResult>> failures;
706                     std::unique_ptr<C2Param> outParam = C2Param::CopyAsStream(
707                         *param.get(), true /*output*/, param->stream());
708                     c2_status_t err =
709                         intf->config({outParam.get()}, C2_MAY_BLOCK, &failures);
710                     if (err == C2_OK) {
711                         work->worklets.front()->output.configUpdate.push_back(
712                             C2Param::Copy(*outParam.get()));
713                     } else {
714                         ALOGE("finishWork: Config update size failed");
715                     }
716                     break;
717                 }
718             }
719         }
720     };
721     if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
722         fillWork(work);
723     } else {
724         finish(index, fillWork);
725     }
726 }
727 
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)728 void C2GoldfishVpxDec::process(const std::unique_ptr<C2Work> &work,
729                                const std::shared_ptr<C2BlockPool> &pool) {
730     DDD("%s %d doing work now", __func__, __LINE__);
731     // Initialize output work
732     work->result = C2_OK;
733     work->workletsProcessed = 0u;
734     work->worklets.front()->output.configUpdate.clear();
735     work->worklets.front()->output.flags = work->input.flags;
736 
737     if (mSignalledError || mSignalledOutputEos) {
738         work->result = C2_BAD_VALUE;
739         return;
740     }
741 
742     size_t inOffset = 0u;
743     size_t inSize = 0u;
744     C2ReadView rView = mDummyReadView;
745     if (!work->input.buffers.empty()) {
746         rView =
747             work->input.buffers[0]->data().linearBlocks().front().map().get();
748         inSize = rView.capacity();
749         if (inSize && rView.error()) {
750             ALOGE("read view map failed %d", rView.error());
751             work->result = C2_CORRUPTED;
752             return;
753         }
754     }
755 
756     checkContext(pool);
757 
758     bool codecConfig =
759         ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0);
760     bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
761 
762     DDD("in buffer attr. size %zu timestamp %d frameindex %d, flags %x", inSize,
763         (int)work->input.ordinal.timestamp.peeku(),
764         (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
765 
766     if (mMode == MODE_VP8) {
767         constexpr uint64_t ONE_SECOND_IN_MICRO_SECOND = 1000 * 1000;
768         // bug: 349159609
769         // note, vp8 does not have the FLAG_CODEC_CONFIG and the test
770         // android.mediav2.cts.DecoderDynamicColorAspectTest test still
771         // expects vp8 to pass. so this hack is to check the time stamp
772         // change to update the color aspect: too early or too late is
773         // a problem as it can cause mismatch of frame and coloraspect
774         DDD("%s %d vp8 last pts is %d current pts is %d",
775                 __func__, __LINE__, mLastPts, (int) work->input.ordinal.timestamp.peeku());
776         if (mLastPts + ONE_SECOND_IN_MICRO_SECOND <= work->input.ordinal.timestamp.peeku()) {
777             codecConfig = true;
778             DDD("%s %d updated codecConfig to true", __func__, __LINE__);
779         } else {
780             DDD("%s %d keep codecConfig to false", __func__, __LINE__);
781         }
782         mLastPts = work->input.ordinal.timestamp.peeku();
783         if (mLastPts == 0) {
784             codecConfig = true;
785         }
786         if (codecConfig) {
787             IntfImpl::Lock lock = mIntf->lock();
788             std::shared_ptr<C2StreamColorAspectsTuning::output> defaultColorAspects =
789             mIntf->getDefaultColorAspects_l();
790             m_primaries = defaultColorAspects->primaries;
791             m_range = defaultColorAspects->range;
792             m_transfer = defaultColorAspects->transfer;
793             m_matrix = defaultColorAspects->matrix;
794         }
795     }
796 
797     if (codecConfig) {
798         {
799             IntfImpl::Lock lock = mIntf->lock();
800             std::shared_ptr<C2StreamColorAspectsTuning::output> defaultColorAspects =
801                 mIntf->getDefaultColorAspects_l();
802             lock.unlock();
803             C2StreamColorAspectsInfo::input codedAspects(0u, defaultColorAspects->range,
804                 defaultColorAspects->primaries, defaultColorAspects->transfer,
805                 defaultColorAspects->matrix);
806             std::vector<std::unique_ptr<C2SettingResult>> failures;
807             (void)mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures);
808         }
809 
810         DDD("%s %d updated coloraspect due to codec config", __func__, __LINE__);
811         if (mMode == MODE_VP9) {
812             fillEmptyWork(work);
813             return;
814         }
815     }
816 
817     sendMetadata();
818 
819     if (inSize) {
820         uint8_t *bitstream = const_cast<uint8_t *>(rView.data() + inOffset);
821         vpx_codec_err_t err = vpx_codec_decode(
822             mCtx, bitstream, inSize, &work->input.ordinal.frameIndex, 0);
823         if (err != 0) {
824             ALOGE("on2 decoder failed to decode frame. err: ");
825             mSignalledError = true;
826             work->workletsProcessed = 1u;
827             work->result = C2_CORRUPTED;
828             return;
829         }
830     }
831 
832     status_t err = outputBuffer(pool, work);
833     if (err == NOT_ENOUGH_DATA) {
834         if (inSize > 0) {
835             DDD("Maybe non-display frame at %lld.",
836                 work->input.ordinal.frameIndex.peekll());
837             // send the work back with empty buffer.
838             inSize = 0;
839         }
840     } else if (err != OK) {
841         ALOGD("Error while getting the output frame out");
842         // work->result would be already filled; do fillEmptyWork() below to
843         // send the work back.
844         inSize = 0;
845     }
846 
847     if (eos) {
848         drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
849         mSignalledOutputEos = true;
850     } else if (!inSize) {
851         fillEmptyWork(work);
852     }
853 }
854 
copyOutputBufferToYuvPlanarFrame(uint8_t * dst,const uint8_t * srcY,const uint8_t * srcU,const uint8_t * srcV,size_t srcYStride,size_t srcUStride,size_t srcVStride,size_t dstYStride,size_t dstUVStride,uint32_t width,uint32_t height)855 static void copyOutputBufferToYuvPlanarFrame(
856     uint8_t *dst, const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
857     size_t srcYStride, size_t srcUStride, size_t srcVStride, size_t dstYStride,
858     size_t dstUVStride, uint32_t width, uint32_t height) {
859     uint8_t *dstStart = dst;
860 
861     for (size_t i = 0; i < height; ++i) {
862         memcpy(dst, srcY, width);
863         srcY += srcYStride;
864         dst += dstYStride;
865     }
866 
867     dst = dstStart + dstYStride * height;
868     for (size_t i = 0; i < height / 2; ++i) {
869         memcpy(dst, srcV, width / 2);
870         srcV += srcVStride;
871         dst += dstUVStride;
872     }
873 
874     dst = dstStart + (dstYStride * height) + (dstUVStride * height / 2);
875     for (size_t i = 0; i < height / 2; ++i) {
876         memcpy(dst, srcU, width / 2);
877         srcU += srcUStride;
878         dst += dstUVStride;
879     }
880 }
881 
setup_ctx_parameters(vpx_codec_ctx_t * ctx,int hostColorBufferId)882 void C2GoldfishVpxDec::setup_ctx_parameters(vpx_codec_ctx_t *ctx,
883                                             int hostColorBufferId) {
884     ctx->width = mWidth;
885     ctx->height = mHeight;
886     ctx->hostColorBufferId = hostColorBufferId;
887     ctx->outputBufferWidth = mWidth;
888     ctx->outputBufferHeight = mHeight;
889     int32_t bpp = 1;
890     ctx->bpp = bpp;
891 }
892 
893 status_t
outputBuffer(const std::shared_ptr<C2BlockPool> & pool,const std::unique_ptr<C2Work> & work)894 C2GoldfishVpxDec::outputBuffer(const std::shared_ptr<C2BlockPool> &pool,
895                                const std::unique_ptr<C2Work> &work) {
896     if (!(work && pool))
897         return BAD_VALUE;
898 
899     // now get the block
900     std::shared_ptr<C2GraphicBlock> block;
901     uint32_t format = HAL_PIXEL_FORMAT_YCBCR_420_888;
902     const C2MemoryUsage usage = {(uint64_t)(BufferUsage::VIDEO_DECODER),
903                                  C2MemoryUsage::CPU_WRITE | C2MemoryUsage::CPU_READ};
904 
905     c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 2), mHeight, format,
906                                               usage, &block);
907     if (err != C2_OK) {
908         ALOGE("fetchGraphicBlock for Output failed with status %d", err);
909         work->result = err;
910         return UNKNOWN_ERROR;
911     }
912 
913     int hostColorBufferId = -1;
914     const bool decodingToHostColorBuffer = mEnableAndroidNativeBuffers;
915     if(decodingToHostColorBuffer){
916         auto c2Handle = block->handle();
917         native_handle_t *grallocHandle =
918             UnwrapNativeCodec2GrallocHandle(c2Handle);
919         hostColorBufferId = getColorBufferHandle(grallocHandle);
920         if (hostColorBufferId > 0) {
921             DDD("found handle %d", hostColorBufferId);
922         } else {
923             DDD("decode to buffer, because handle %d is invalid",
924                 hostColorBufferId);
925             // change to -1 so host knows it is definitely invalid
926             // 0 is a bit confusing
927             hostColorBufferId = -1;
928         }
929     }
930     setup_ctx_parameters(mCtx, hostColorBufferId);
931 
932     vpx_image_t *img = vpx_codec_get_frame(mCtx);
933 
934     if (!img)
935         return NOT_ENOUGH_DATA;
936 
937     if (img->d_w != mWidth || img->d_h != mHeight) {
938         DDD("updating w %d h %d to w %d h %d", mWidth, mHeight, img->d_w,
939             img->d_h);
940         mWidth = img->d_w;
941         mHeight = img->d_h;
942 
943         // need to re-allocate since size changed, especially for byte buffer
944         // mode
945         if (true) {
946             c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 2), mHeight,
947                                                       format, usage, &block);
948             if (err != C2_OK) {
949                 ALOGE("fetchGraphicBlock for Output failed with status %d",
950                       err);
951                 work->result = err;
952                 return UNKNOWN_ERROR;
953             }
954         }
955 
956         C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
957         std::vector<std::unique_ptr<C2SettingResult>> failures;
958         c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
959         if (err == C2_OK) {
960             work->worklets.front()->output.configUpdate.push_back(
961                 C2Param::Copy(size));
962         } else {
963             ALOGE("Config update size failed");
964             mSignalledError = true;
965             work->workletsProcessed = 1u;
966             work->result = C2_CORRUPTED;
967             return UNKNOWN_ERROR;
968         }
969     }
970     if (img->fmt != VPX_IMG_FMT_I420 && img->fmt != VPX_IMG_FMT_I42016) {
971         ALOGE("img->fmt %d not supported", img->fmt);
972         mSignalledError = true;
973         work->workletsProcessed = 1u;
974         work->result = C2_CORRUPTED;
975         return false;
976     }
977 
978     if (img->fmt == VPX_IMG_FMT_I42016) {
979         IntfImpl::Lock lock = mIntf->lock();
980         std::shared_ptr<C2StreamColorAspectsTuning::output>
981             defaultColorAspects = mIntf->getDefaultColorAspects_l();
982 
983         if (defaultColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
984             defaultColorAspects->matrix == C2Color::MATRIX_BT2020 &&
985             defaultColorAspects->transfer == C2Color::TRANSFER_ST2084) {
986             format = HAL_PIXEL_FORMAT_RGBA_1010102;
987         }
988     }
989 
990     if (!decodingToHostColorBuffer) {
991 
992         C2GraphicView wView = block->map().get();
993         if (wView.error()) {
994             ALOGE("graphic view map failed %d", wView.error());
995             work->result = C2_CORRUPTED;
996             return UNKNOWN_ERROR;
997         }
998 
999         DDD("provided (%dx%d) required (%dx%d), out frameindex %lld",
1000             block->width(), block->height(), mWidth, mHeight,
1001             ((c2_cntr64_t *)img->user_priv)->peekll());
1002 
1003         uint8_t *dst =
1004             const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_Y]);
1005         size_t srcYStride = mWidth;
1006         size_t srcUStride = mWidth / 2;
1007         size_t srcVStride = mWidth / 2;
1008         C2PlanarLayout layout = wView.layout();
1009         size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
1010         size_t dstUVStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
1011 
1012         if (img->fmt == VPX_IMG_FMT_I42016) {
1013             ALOGW("WARNING: not I42016 is not supported !!!");
1014         } else if (1) {
1015             const uint8_t *srcY = (const uint8_t *)mCtx->dst;
1016             const uint8_t *srcV = srcY + mWidth * mHeight;
1017             const uint8_t *srcU = srcV + mWidth * mHeight / 4;
1018             // TODO: the following crashes
1019             copyOutputBufferToYuvPlanarFrame(dst, srcY, srcU, srcV, srcYStride,
1020                                              srcUStride, srcVStride, dstYStride,
1021                                              dstUVStride, mWidth, mHeight);
1022             // memcpy(dst, srcY, mWidth * mHeight / 2);
1023         }
1024     }
1025     DDD("provided (%dx%d) required (%dx%d), out frameindex %lld",
1026         block->width(), block->height(), mWidth, mHeight,
1027         ((c2_cntr64_t *)img->user_priv)->peekll());
1028 
1029     finishWork(((c2_cntr64_t *)img->user_priv)->peekull(), work,
1030                std::move(block));
1031     return OK;
1032 }
1033 
1034 c2_status_t
drainInternal(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool,const std::unique_ptr<C2Work> & work)1035 C2GoldfishVpxDec::drainInternal(uint32_t drainMode,
1036                                 const std::shared_ptr<C2BlockPool> &pool,
1037                                 const std::unique_ptr<C2Work> &work) {
1038     if (drainMode == NO_DRAIN) {
1039         ALOGW("drain with NO_DRAIN: no-op");
1040         return C2_OK;
1041     }
1042     if (drainMode == DRAIN_CHAIN) {
1043         ALOGW("DRAIN_CHAIN not supported");
1044         return C2_OMITTED;
1045     }
1046 
1047     while (outputBuffer(pool, work) == OK) {
1048     }
1049 
1050     if (drainMode == DRAIN_COMPONENT_WITH_EOS && work &&
1051         work->workletsProcessed == 0u) {
1052         fillEmptyWork(work);
1053     }
1054 
1055     return C2_OK;
1056 }
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)1057 c2_status_t C2GoldfishVpxDec::drain(uint32_t drainMode,
1058                                     const std::shared_ptr<C2BlockPool> &pool) {
1059     return drainInternal(drainMode, pool, nullptr);
1060 }
1061 
1062 class C2GoldfishVpxFactory : public C2ComponentFactory {
1063   public:
C2GoldfishVpxFactory()1064     C2GoldfishVpxFactory()
1065         : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
1066               GoldfishComponentStore::Create()->getParamReflector())) {
1067 
1068         ALOGI("platform store is %p, reflector is %p",
1069               GetCodec2PlatformComponentStore().get(),
1070               GetCodec2PlatformComponentStore()->getParamReflector().get());
1071     }
1072 
1073     virtual c2_status_t
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)1074     createComponent(c2_node_id_t id,
1075                     std::shared_ptr<C2Component> *const component,
1076                     std::function<void(C2Component *)> deleter) override {
1077         *component = std::shared_ptr<C2Component>(
1078             new C2GoldfishVpxDec(
1079                 COMPONENT_NAME, id,
1080                 std::make_shared<C2GoldfishVpxDec::IntfImpl>(mHelper)),
1081             deleter);
1082         return C2_OK;
1083     }
1084 
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)1085     virtual c2_status_t createInterface(
1086         c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *const interface,
1087         std::function<void(C2ComponentInterface *)> deleter) override {
1088         *interface = std::shared_ptr<C2ComponentInterface>(
1089             new SimpleInterface<C2GoldfishVpxDec::IntfImpl>(
1090                 COMPONENT_NAME, id,
1091                 std::make_shared<C2GoldfishVpxDec::IntfImpl>(mHelper)),
1092             deleter);
1093         return C2_OK;
1094     }
1095 
1096     virtual ~C2GoldfishVpxFactory() override = default;
1097 
1098   private:
1099     std::shared_ptr<C2ReflectorHelper> mHelper;
1100 };
1101 
1102 } // namespace android
1103 
CreateCodec2Factory()1104 extern "C" ::C2ComponentFactory *CreateCodec2Factory() {
1105     DDD("in %s", __func__);
1106     return new ::android::C2GoldfishVpxFactory();
1107 }
1108 
DestroyCodec2Factory(::C2ComponentFactory * factory)1109 extern "C" void DestroyCodec2Factory(::C2ComponentFactory *factory) {
1110     DDD("in %s", __func__);
1111     delete factory;
1112 }
1113