xref: /aosp_15_r20/frameworks/av/media/codec2/components/apv/C2SoftApvDec.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 "C2SoftApvDec"
19 #include <log/log.h>
20 
21 #include <android_media_swcodec_flags.h>
22 
23 #include <media/stagefright/foundation/AUtils.h>
24 #include <media/stagefright/foundation/MediaDefs.h>
25 
26 #include <C2Debug.h>
27 #include <C2PlatformSupport.h>
28 #include <Codec2BufferUtils.h>
29 #include <Codec2CommonUtils.h>
30 #include <Codec2Mapper.h>
31 #include <SimpleC2Interface.h>
32 #include "C2SoftApvDec.h"
33 
34 #include <cutils/properties.h>
35 
36 const char* MEDIA_MIMETYPE_VIDEO_APV = "video/apv";
37 
38 #define MAX_NUM_FRMS (1)  // supports only 1-frame output
39 #define FRM_IDX (0)       // supports only 1-frame output
40 // check generic frame or not
41 #define IS_NON_AUX_FRM(frm)                              \
42     (((frm)->pbu_type == OAPV_PBU_TYPE_PRIMARY_FRAME) || \
43      ((frm)->pbu_type == OAPV_PBU_TYPE_NON_PRIMARY_FRAME))
44 // check auxiliary frame or not
45 #define IS_AUX_FRM(frm) (!(IS_NON_AUX_FRM(frm)))
46 #define OUTPUT_CSP_NATIVE (0)
47 #define OUTPUT_CSP_P210 (1)
48 
49 namespace android {
50 namespace {
51 constexpr char COMPONENT_NAME[] = "c2.android.apv.decoder";
52 constexpr uint32_t kDefaultOutputDelay = 8;
53 constexpr uint32_t kMaxOutputDelay = 16;
54 constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
55 }  // namespace
56 
57 class C2SoftApvDec::IntfImpl : public SimpleInterface<void>::BaseParams {
58   public:
IntfImpl(const std::shared_ptr<C2ReflectorHelper> & helper)59     explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper)
60         : SimpleInterface<void>::BaseParams(helper, COMPONENT_NAME, C2Component::KIND_DECODER,
61                                             C2Component::DOMAIN_VIDEO, MEDIA_MIMETYPE_VIDEO_APV) {
62         noPrivateBuffers();  // TODO: account for our buffers here.
63         noInputReferences();
64         noOutputReferences();
65         noInputLatency();
66         noTimeStretch();
67 
68         addParameter(DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
69                              .withConstValue(new C2ComponentAttributesSetting(
70                                      C2Component::ATTRIB_IS_TEMPORAL))
71                              .build());
72 
73         addParameter(DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
74                              .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
75                              .withFields({
76                                      C2F(mSize, width).inRange(2, 4096),
77                                      C2F(mSize, height).inRange(2, 4096),
78                              })
79                              .withSetter(SizeSetter)
80                              .build());
81 
82         addParameter(
83                 DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
84                         .withDefault(new C2StreamProfileLevelInfo::input(
85                                 0u, C2Config::PROFILE_APV_422_10))
86                         .withFields(
87                                 {C2F(mProfileLevel, profile).oneOf({C2Config::PROFILE_APV_422_10}),
88                                  C2F(mProfileLevel, level)
89                                          .oneOf({
90                                                 C2Config::LEVEL_APV_1_BAND_0,
91                                                 C2Config::LEVEL_APV_1_1_BAND_0,
92                                                 C2Config::LEVEL_APV_2_BAND_0,
93                                                 C2Config::LEVEL_APV_2_1_BAND_0,
94                                                 C2Config::LEVEL_APV_3_BAND_0,
95                                                 C2Config::LEVEL_APV_3_1_BAND_0,
96                                                 C2Config::LEVEL_APV_4_BAND_0,
97                                                 C2Config::LEVEL_APV_4_1_BAND_0,
98                                                 C2Config::LEVEL_APV_5_BAND_0,
99                                                 C2Config::LEVEL_APV_5_1_BAND_0,
100                                                 C2Config::LEVEL_APV_6_BAND_0,
101                                                 C2Config::LEVEL_APV_6_1_BAND_0,
102                                                 C2Config::LEVEL_APV_7_BAND_0,
103                                                 C2Config::LEVEL_APV_7_1_BAND_0,
104                                                 C2Config::LEVEL_APV_1_BAND_1,
105                                                 C2Config::LEVEL_APV_1_1_BAND_1,
106                                                 C2Config::LEVEL_APV_2_BAND_1,
107                                                 C2Config::LEVEL_APV_2_1_BAND_1,
108                                                 C2Config::LEVEL_APV_3_BAND_1,
109                                                 C2Config::LEVEL_APV_3_1_BAND_1,
110                                                 C2Config::LEVEL_APV_4_BAND_1,
111                                                 C2Config::LEVEL_APV_4_1_BAND_1,
112                                                 C2Config::LEVEL_APV_5_BAND_1,
113                                                 C2Config::LEVEL_APV_5_1_BAND_1,
114                                                 C2Config::LEVEL_APV_6_BAND_1,
115                                                 C2Config::LEVEL_APV_6_1_BAND_1,
116                                                 C2Config::LEVEL_APV_7_BAND_1,
117                                                 C2Config::LEVEL_APV_7_1_BAND_1,
118                                                 C2Config::LEVEL_APV_1_BAND_2,
119                                                 C2Config::LEVEL_APV_1_1_BAND_2,
120                                                 C2Config::LEVEL_APV_2_BAND_2,
121                                                 C2Config::LEVEL_APV_2_1_BAND_2,
122                                                 C2Config::LEVEL_APV_3_BAND_2,
123                                                 C2Config::LEVEL_APV_3_1_BAND_2,
124                                                 C2Config::LEVEL_APV_4_BAND_2,
125                                                 C2Config::LEVEL_APV_4_1_BAND_2,
126                                                 C2Config::LEVEL_APV_5_BAND_2,
127                                                 C2Config::LEVEL_APV_5_1_BAND_2,
128                                                 C2Config::LEVEL_APV_6_BAND_2,
129                                                 C2Config::LEVEL_APV_6_1_BAND_2,
130                                                 C2Config::LEVEL_APV_7_BAND_2,
131                                                 C2Config::LEVEL_APV_7_1_BAND_2,
132                                                 C2Config::LEVEL_APV_1_BAND_3,
133                                                 C2Config::LEVEL_APV_1_1_BAND_3,
134                                                 C2Config::LEVEL_APV_2_BAND_3,
135                                                 C2Config::LEVEL_APV_2_1_BAND_3,
136                                                 C2Config::LEVEL_APV_3_BAND_3,
137                                                 C2Config::LEVEL_APV_3_1_BAND_3,
138                                                 C2Config::LEVEL_APV_4_BAND_3,
139                                                 C2Config::LEVEL_APV_4_1_BAND_3,
140                                                 C2Config::LEVEL_APV_5_BAND_3,
141                                                 C2Config::LEVEL_APV_5_1_BAND_3,
142                                                 C2Config::LEVEL_APV_6_BAND_3,
143                                                 C2Config::LEVEL_APV_6_1_BAND_3,
144                                                 C2Config::LEVEL_APV_7_BAND_3,
145                                                 C2Config::LEVEL_APV_7_1_BAND_3,
146                                                  })})
147                         .withSetter(ProfileLevelSetter, mSize)
148                         .build());
149 
150         mHdr10PlusInfoInput = C2StreamHdr10PlusInfo::input::AllocShared(0);
151         addParameter(DefineParam(mHdr10PlusInfoInput, C2_PARAMKEY_INPUT_HDR10_PLUS_INFO)
152                              .withDefault(mHdr10PlusInfoInput)
153                              .withFields({
154                                      C2F(mHdr10PlusInfoInput, m.value).any(),
155                              })
156                              .withSetter(Hdr10PlusInfoInputSetter)
157                              .build());
158 
159         mHdr10PlusInfoOutput = C2StreamHdr10PlusInfo::output::AllocShared(0);
160         addParameter(DefineParam(mHdr10PlusInfoOutput, C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO)
161                              .withDefault(mHdr10PlusInfoOutput)
162                              .withFields({
163                                      C2F(mHdr10PlusInfoOutput, m.value).any(),
164                              })
165                              .withSetter(Hdr10PlusInfoOutputSetter)
166                              .build());
167 
168         // default static info
169         C2HdrStaticMetadataStruct defaultStaticInfo{};
170         helper->addStructDescriptors<C2MasteringDisplayColorVolumeStruct, C2ColorXyStruct>();
171         addParameter(
172                 DefineParam(mHdrStaticInfo, C2_PARAMKEY_HDR_STATIC_INFO)
173                         .withDefault(new C2StreamHdrStaticInfo::output(0u, defaultStaticInfo))
174                         .withFields({C2F(mHdrStaticInfo, mastering.red.x).inRange(0, 1),
175                                      C2F(mHdrStaticInfo, mastering.red.y).inRange(0, 1),
176                                      C2F(mHdrStaticInfo, mastering.green.x).inRange(0, 1),
177                                      C2F(mHdrStaticInfo, mastering.green.y).inRange(0, 1),
178                                      C2F(mHdrStaticInfo, mastering.blue.x).inRange(0, 1),
179                                      C2F(mHdrStaticInfo, mastering.blue.y).inRange(0, 1),
180                                      C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
181                                      C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
182                                      C2F(mHdrStaticInfo, mastering.maxLuminance).inRange(0, 65535),
183                                      C2F(mHdrStaticInfo, mastering.minLuminance).inRange(0, 6.5535),
184                                      C2F(mHdrStaticInfo, maxCll).inRange(0, 0XFFFF),
185                                      C2F(mHdrStaticInfo, maxFall).inRange(0, 0XFFFF)})
186                         .withSetter(HdrStaticInfoSetter)
187                         .build());
188 
189         addParameter(DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
190                              .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240))
191                              .withFields({
192                                      C2F(mSize, width).inRange(2, 4096, 2),
193                                      C2F(mSize, height).inRange(2, 4096, 2),
194                              })
195                              .withSetter(MaxPictureSizeSetter, mSize)
196                              .build());
197 
198         addParameter(
199                 DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
200                         .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
201                         .withFields({
202                                 C2F(mMaxInputSize, value).any(),
203                         })
204                         .calculatedAs(MaxInputSizeSetter, mMaxSize)
205                         .build());
206 
207         C2ChromaOffsetStruct locations[1] = {C2ChromaOffsetStruct::ITU_YUV_420_0()};
208         std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
209                 C2StreamColorInfo::output::AllocShared(1u, 0u, 8u /* bitDepth */, C2Color::YUV_420);
210         memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
211 
212         defaultColorInfo = C2StreamColorInfo::output::AllocShared(
213                 {C2ChromaOffsetStruct::ITU_YUV_420_0()}, 0u, 8u /* bitDepth */, C2Color::YUV_420);
214         helper->addStructDescriptors<C2ChromaOffsetStruct>();
215         addParameter(DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
216                              .withConstValue(defaultColorInfo)
217                              .build());
218 
219         addParameter(DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
220                              .withDefault(new C2StreamColorAspectsTuning::output(
221                                      0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
222                                      C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
223                              .withFields({C2F(mDefaultColorAspects, range)
224                                                   .inRange(C2Color::RANGE_UNSPECIFIED,
225                                                            C2Color::RANGE_OTHER),
226                                           C2F(mDefaultColorAspects, primaries)
227                                                   .inRange(C2Color::PRIMARIES_UNSPECIFIED,
228                                                            C2Color::PRIMARIES_OTHER),
229                                           C2F(mDefaultColorAspects, transfer)
230                                                   .inRange(C2Color::TRANSFER_UNSPECIFIED,
231                                                            C2Color::TRANSFER_OTHER),
232                                           C2F(mDefaultColorAspects, matrix)
233                                                   .inRange(C2Color::MATRIX_UNSPECIFIED,
234                                                            C2Color::MATRIX_OTHER)})
235                              .withSetter(DefaultColorAspectsSetter)
236                              .build());
237 
238         addParameter(DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
239                              .withDefault(new C2StreamColorAspectsInfo::input(
240                                      0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
241                                      C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
242                              .withFields({C2F(mCodedColorAspects, range)
243                                                   .inRange(C2Color::RANGE_UNSPECIFIED,
244                                                            C2Color::RANGE_OTHER),
245                                           C2F(mCodedColorAspects, primaries)
246                                                   .inRange(C2Color::PRIMARIES_UNSPECIFIED,
247                                                            C2Color::PRIMARIES_OTHER),
248                                           C2F(mCodedColorAspects, transfer)
249                                                   .inRange(C2Color::TRANSFER_UNSPECIFIED,
250                                                            C2Color::TRANSFER_OTHER),
251                                           C2F(mCodedColorAspects, matrix)
252                                                   .inRange(C2Color::MATRIX_UNSPECIFIED,
253                                                            C2Color::MATRIX_OTHER)})
254                              .withSetter(CodedColorAspectsSetter)
255                              .build());
256 
257         addParameter(
258                 DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
259                         .withDefault(new C2StreamColorAspectsInfo::output(
260                                 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
261                                 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
262                         .withFields(
263                                 {C2F(mColorAspects, range)
264                                          .inRange(C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
265                                  C2F(mColorAspects, primaries)
266                                          .inRange(C2Color::PRIMARIES_UNSPECIFIED,
267                                                   C2Color::PRIMARIES_OTHER),
268                                  C2F(mColorAspects, transfer)
269                                          .inRange(C2Color::TRANSFER_UNSPECIFIED,
270                                                   C2Color::TRANSFER_OTHER),
271                                  C2F(mColorAspects, matrix)
272                                          .inRange(C2Color::MATRIX_UNSPECIFIED,
273                                                   C2Color::MATRIX_OTHER)})
274                         .withSetter(ColorAspectsSetter, mDefaultColorAspects, mCodedColorAspects)
275                         .build());
276 
277         // TODO: support more formats?
278         std::vector<uint32_t> pixelFormats = {HAL_PIXEL_FORMAT_YCBCR_420_888};
279         if (isHalPixelFormatSupported((AHardwareBuffer_Format)HAL_PIXEL_FORMAT_YCBCR_P010)) {
280             pixelFormats.push_back(HAL_PIXEL_FORMAT_YCBCR_P010);
281         }
282         if (isHalPixelFormatSupported((AHardwareBuffer_Format)AHARDWAREBUFFER_FORMAT_YCbCr_P210)) {
283             pixelFormats.push_back(AHARDWAREBUFFER_FORMAT_YCbCr_P210);
284         }
285 
286         // If color format surface isn't added to supported formats, there is no way to know
287         // when the color-format is configured to surface. This is necessary to be able to
288         // choose 10-bit format while decoding 10-bit clips in surface mode.
289         pixelFormats.push_back(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
290         addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
291                              .withDefault(new C2StreamPixelFormatInfo::output(
292                                      0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
293                              .withFields({C2F(mPixelFormat, value).oneOf(pixelFormats)})
294                              .withSetter((Setter<decltype(*mPixelFormat)>::StrictValueWithNoDeps))
295                              .build());
296     }
297 
SizeSetter(bool mayBlock,const C2P<C2StreamPictureSizeInfo::output> & oldMe,C2P<C2StreamPictureSizeInfo::output> & me)298     static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::output>& oldMe,
299                           C2P<C2StreamPictureSizeInfo::output>& me) {
300         (void)mayBlock;
301         ALOGV("%s - %d x %d", __FUNCTION__, me.v.width, me.v.height);
302         C2R res = C2R::Ok();
303         if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
304             res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
305             me.set().width = oldMe.v.width;
306         }
307         if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
308             res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
309             me.set().height = oldMe.v.height;
310         }
311         return res;
312     }
313 
MaxPictureSizeSetter(bool mayBlock,C2P<C2StreamMaxPictureSizeTuning::output> & me,const C2P<C2StreamPictureSizeInfo::output> & size)314     static C2R MaxPictureSizeSetter(bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output>& me,
315                                     const C2P<C2StreamPictureSizeInfo::output>& size) {
316         (void)mayBlock;
317         ALOGV("%s - %d x %d", __FUNCTION__, me.v.width, me.v.height);
318         // TODO: get max width/height from the size's field helpers vs.
319         // hardcoding
320         me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4096u);
321         me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4096u);
322         return C2R::Ok();
323     }
324 
MaxInputSizeSetter(bool mayBlock,C2P<C2StreamMaxBufferSizeInfo::input> & me,const C2P<C2StreamMaxPictureSizeTuning::output> & maxSize)325     static C2R MaxInputSizeSetter(bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input>& me,
326                                   const C2P<C2StreamMaxPictureSizeTuning::output>& maxSize) {
327         (void)mayBlock;
328         ALOGV("%s", __FUNCTION__);
329         // assume compression ratio of 2, but enforce a floor
330         me.set().value =
331                 c2_max((((maxSize.v.width + 63) / 64) * ((maxSize.v.height + 63) / 64) * 3072),
332                        kMinInputBufferSize);
333         return C2R::Ok();
334     }
335 
DefaultColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsTuning::output> & me)336     static C2R DefaultColorAspectsSetter(bool mayBlock,
337                                          C2P<C2StreamColorAspectsTuning::output>& me) {
338         (void)mayBlock;
339         ALOGV("%s - range: %u, primary: %u, transfer: %u, matrix: %u", __FUNCTION__, me.v.range,
340               me.v.primaries, me.v.transfer, me.v.matrix);
341         if (me.v.range > C2Color::RANGE_OTHER) {
342             me.set().range = C2Color::RANGE_OTHER;
343         }
344         if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
345             me.set().primaries = C2Color::PRIMARIES_OTHER;
346         }
347         if (me.v.transfer > C2Color::TRANSFER_OTHER) {
348             me.set().transfer = C2Color::TRANSFER_OTHER;
349         }
350         if (me.v.matrix > C2Color::MATRIX_OTHER) {
351             me.set().matrix = C2Color::MATRIX_OTHER;
352         }
353         return C2R::Ok();
354     }
355 
CodedColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsInfo::input> & me)356     static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input>& me) {
357         (void)mayBlock;
358         ALOGV("%s - range: %u, primaries: %u, transfer: %u, matrix: %u", __func__, me.v.range,
359               me.v.primaries, me.v.transfer, me.v.matrix);
360         if (me.v.range > C2Color::RANGE_OTHER) {
361             me.set().range = C2Color::RANGE_OTHER;
362         }
363         if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
364             me.set().primaries = C2Color::PRIMARIES_OTHER;
365         }
366         if (me.v.transfer > C2Color::TRANSFER_OTHER) {
367             me.set().transfer = C2Color::TRANSFER_OTHER;
368         }
369         if (me.v.matrix > C2Color::MATRIX_OTHER) {
370             me.set().matrix = C2Color::MATRIX_OTHER;
371         }
372         return C2R::Ok();
373     }
374 
ColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsInfo::output> & me,const C2P<C2StreamColorAspectsTuning::output> & def,const C2P<C2StreamColorAspectsInfo::input> & coded)375     static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output>& me,
376                                   const C2P<C2StreamColorAspectsTuning::output>& def,
377                                   const C2P<C2StreamColorAspectsInfo::input>& coded) {
378         (void)mayBlock;
379         ALOGV("%s", __FUNCTION__);
380         // take default values for all unspecified fields, and coded values for specified ones
381         ALOGV("%s - coded range: %u, primaries: %u, transfer: %u, matrix: %u",
382              __func__, coded.v.range, coded.v.primaries, coded.v.transfer, coded.v.matrix);
383         me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range;
384         me.set().primaries =
385                 coded.v.primaries == PRIMARIES_UNSPECIFIED ? def.v.primaries : coded.v.primaries;
386         me.set().transfer =
387                 coded.v.transfer == TRANSFER_UNSPECIFIED ? def.v.transfer : coded.v.transfer;
388         me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix : coded.v.matrix;
389         ALOGV("%s - me.v.range = %u, me.v.primaries = %u, me.v.transfer = %u, me.v.matrix = %u",
390               __func__, me.v.range, me.v.primaries, me.v.transfer, me.v.matrix);
391         return C2R::Ok();
392     }
393 
ProfileLevelSetter(bool mayBlock,C2P<C2StreamProfileLevelInfo::input> & me,const C2P<C2StreamPictureSizeInfo::output> & size)394     static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input>& me,
395                                   const C2P<C2StreamPictureSizeInfo::output>& size) {
396         (void)mayBlock;
397         ALOGV("%s", __FUNCTION__);
398         (void)size;
399         (void)me;  // TODO: validate
400         return C2R::Ok();
401     }
402 
getDefaultColorAspects_l()403     std::shared_ptr<C2StreamColorAspectsTuning::output> getDefaultColorAspects_l() {
404         ALOGV("%s - mDefaultColorAspects: %u", __FUNCTION__, mDefaultColorAspects->primaries);
405         return mDefaultColorAspects;
406     }
407 
getColorAspects_l()408     std::shared_ptr<C2StreamColorAspectsInfo::output> getColorAspects_l() {
409         ALOGV("%s - mColorAspects: %u", __FUNCTION__, mColorAspects->primaries);
410         return mColorAspects;
411     }
412 
Hdr10PlusInfoInputSetter(bool mayBlock,C2P<C2StreamHdr10PlusInfo::input> & me)413     static C2R Hdr10PlusInfoInputSetter(bool mayBlock, C2P<C2StreamHdr10PlusInfo::input>& me) {
414         (void)mayBlock;
415         ALOGV("%s", __FUNCTION__);
416         (void)me;  // TODO: validate
417         return C2R::Ok();
418     }
419 
Hdr10PlusInfoOutputSetter(bool mayBlock,C2P<C2StreamHdr10PlusInfo::output> & me)420     static C2R Hdr10PlusInfoOutputSetter(bool mayBlock, C2P<C2StreamHdr10PlusInfo::output>& me) {
421         (void)mayBlock;
422         ALOGV("%s", __FUNCTION__);
423         (void)me;  // TODO: validate
424         return C2R::Ok();
425     }
426 
427     // unsafe getters
getPixelFormat_l() const428     std::shared_ptr<C2StreamPixelFormatInfo::output> getPixelFormat_l() const {
429         return mPixelFormat;
430     }
431 
HdrStaticInfoSetter(bool mayBlock,C2P<C2StreamHdrStaticInfo::output> & me)432     static C2R HdrStaticInfoSetter(bool mayBlock, C2P<C2StreamHdrStaticInfo::output>& me) {
433         (void)mayBlock;
434         ALOGV("%s", __FUNCTION__);
435         if (me.v.mastering.red.x > 1) {
436             me.set().mastering.red.x = 1;
437         }
438         if (me.v.mastering.red.y > 1) {
439             me.set().mastering.red.y = 1;
440         }
441         if (me.v.mastering.green.x > 1) {
442             me.set().mastering.green.x = 1;
443         }
444         if (me.v.mastering.green.y > 1) {
445             me.set().mastering.green.y = 1;
446         }
447         if (me.v.mastering.blue.x > 1) {
448             me.set().mastering.blue.x = 1;
449         }
450         if (me.v.mastering.blue.y > 1) {
451             me.set().mastering.blue.y = 1;
452         }
453         if (me.v.mastering.white.x > 1) {
454             me.set().mastering.white.x = 1;
455         }
456         if (me.v.mastering.white.y > 1) {
457             me.set().mastering.white.y = 1;
458         }
459         if (me.v.mastering.maxLuminance > 65535.0) {
460             me.set().mastering.maxLuminance = 65535.0;
461         }
462         if (me.v.mastering.minLuminance > 6.5535) {
463             me.set().mastering.minLuminance = 6.5535;
464         }
465         if (me.v.maxCll > 65535.0) {
466             me.set().maxCll = 65535.0;
467         }
468         if (me.v.maxFall > 65535.0) {
469             me.set().maxFall = 65535.0;
470         }
471         return C2R::Ok();
472     }
473 
474   private:
475     std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
476     std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
477     std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize;
478     std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize;
479     std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
480     std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
481     std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
482     std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects;
483     std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
484     std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput;
485     std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput;
486     std::shared_ptr<C2StreamHdrStaticInfo::output> mHdrStaticInfo;
487 };
488 
ivd_aligned_free(void * ctxt,void * mem)489 static void ivd_aligned_free(void* ctxt, void* mem) {
490     (void)ctxt;
491     free(mem);
492 }
493 
C2SoftApvDec(const char * name,c2_node_id_t id,const std::shared_ptr<IntfImpl> & intfImpl)494 C2SoftApvDec::C2SoftApvDec(const char* name, c2_node_id_t id,
495                            const std::shared_ptr<IntfImpl>& intfImpl)
496     : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
497       mIntf(intfImpl),
498       mDecHandle(nullptr),
499       mOutBufferFlush(nullptr),
500       mIvColorformat(IV_YUV_420P),
501       mOutputDelay(kDefaultOutputDelay),
502       mHeaderDecoded(false),
503       mOutIndex(0u),
504       mHalPixelFormat(HAL_PIXEL_FORMAT_YV12),
505       mWidth(320),
506       mHeight(240),
507       mSignalledOutputEos(false),
508       mSignalledError(false) {
509     oapvdHandle = NULL;
510     oapvmHandle = NULL;
511     outputCsp = OUTPUT_CSP_NATIVE;
512 }
513 
~C2SoftApvDec()514 C2SoftApvDec::~C2SoftApvDec() {
515     onRelease();
516 }
517 
onInit()518 c2_status_t C2SoftApvDec::onInit() {
519     ALOGV("%s", __FUNCTION__);
520     status_t err = initDecoder();
521     return err == OK ? C2_OK : C2_CORRUPTED;
522 }
523 
onStop()524 c2_status_t C2SoftApvDec::onStop() {
525     ALOGV("%s", __FUNCTION__);
526     if (OK != resetDecoder()) return C2_CORRUPTED;
527     resetPlugin();
528     return C2_OK;
529 }
530 
onReset()531 void C2SoftApvDec::onReset() {
532     ALOGV("%s", __FUNCTION__);
533     (void)onStop();
534 }
535 
deleteDecoder()536 status_t C2SoftApvDec::deleteDecoder() {
537     ALOGV("%s", __FUNCTION__);
538     if (oapvdHandle) {
539         oapvd_delete(oapvdHandle);
540         oapvdHandle = NULL;
541     }
542     if (oapvmHandle) {
543         oapvm_delete(oapvmHandle);
544         oapvmHandle = NULL;
545     }
546     for (int i = 0; i < ofrms.num_frms; i++) {
547         if (ofrms.frm[i].imgb != NULL) {
548             ofrms.frm[i].imgb->release(ofrms.frm[i].imgb);
549             ofrms.frm[i].imgb = NULL;
550         }
551     }
552     return OK;
553 }
554 
onRelease()555 void C2SoftApvDec::onRelease() {
556     ALOGV("%s", __FUNCTION__);
557     (void)deleteDecoder();
558     if (mOutBufferFlush) {
559         ivd_aligned_free(nullptr, mOutBufferFlush);
560         mOutBufferFlush = nullptr;
561     }
562     if (mOutBlock) {
563         mOutBlock.reset();
564     }
565 }
566 
onFlush_sm()567 c2_status_t C2SoftApvDec::onFlush_sm() {
568     ALOGV("%s", __FUNCTION__);
569     mSignalledError = false;
570     mSignalledOutputEos = false;
571     return C2_OK;
572 }
573 
createDecoder()574 status_t C2SoftApvDec::createDecoder() {
575     ALOGV("%s", __FUNCTION__);
576     return OK;
577 }
578 
initDecoder()579 status_t C2SoftApvDec::initDecoder() {
580     int ret;
581     mSignalledError = false;
582     mSignalledOutputEos = false;
583 
584     mHalPixelFormat = HAL_PIXEL_FORMAT_YV12;
585     {
586         IntfImpl::Lock lock = mIntf->lock();
587         mPixelFormatInfo = mIntf->getPixelFormat_l();
588         ALOGW("Hal pixel format = %d", mPixelFormatInfo->value);
589     }
590     memset(&cdesc, 0, sizeof(oapvd_cdesc_t));
591 
592     cdesc.threads = 1;  // default
593     oapvdHandle = oapvd_create(&cdesc, &ret);
594     if (oapvdHandle == NULL) {
595         ALOGE("ERROR: cannot create APV decoder (err=%d)\n", ret);
596         return C2_NO_INIT;
597     }
598 
599     memset(&ofrms, 0, sizeof(oapv_frms_t));
600 
601     oapvmHandle = oapvm_create(&ret);
602     if (OAPV_FAILED(ret)) {
603         ALOGE("oapvm create failed");
604         oapvd_delete(oapvdHandle);
605         oapvdHandle = NULL;
606         return C2_NO_INIT;
607     }
608 
609     ALOGV("oapvd init done");
610     return OK;
611 }
612 
setFlushMode()613 status_t C2SoftApvDec::setFlushMode() {
614     ALOGV("%s", __FUNCTION__);
615     return OK;
616 }
617 
resetDecoder()618 status_t C2SoftApvDec::resetDecoder() {
619     ALOGV("%s", __FUNCTION__);
620     return OK;
621 }
622 
resetPlugin()623 void C2SoftApvDec::resetPlugin() {
624     ALOGV("%s", __FUNCTION__);
625     mSignalledOutputEos = false;
626     if (mOutBlock) {
627         mOutBlock.reset();
628     }
629 }
630 
fillEmptyWork(const std::unique_ptr<C2Work> & work)631 void fillEmptyWork(const std::unique_ptr<C2Work>& work) {
632     uint32_t flags = 0;
633     if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
634         flags |= C2FrameData::FLAG_END_OF_STREAM;
635         ALOGV("signalling eos");
636     }
637     work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
638     work->worklets.front()->output.buffers.clear();
639     work->worklets.front()->output.ordinal = work->input.ordinal;
640     work->workletsProcessed = 1u;
641 }
642 
finishWork(uint64_t index,const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2GraphicBlock> & block)643 void C2SoftApvDec::finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
644                               const std::shared_ptr<C2GraphicBlock>& block) {
645     std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(block, C2Rect(mWidth, mHeight));
646 
647     {
648         IntfImpl::Lock lock = mIntf->lock();
649         buffer->setInfo(mIntf->getColorAspects_l());
650     }
651 
652     class FillWork {
653       public:
654         FillWork(uint32_t flags, C2WorkOrdinalStruct ordinal,
655                  const std::shared_ptr<C2Buffer>& buffer)
656             : mFlags(flags), mOrdinal(ordinal), mBuffer(buffer) {}
657         ~FillWork() = default;
658 
659         void operator()(const std::unique_ptr<C2Work>& work) {
660             work->worklets.front()->output.flags = (C2FrameData::flags_t)mFlags;
661             work->worklets.front()->output.buffers.clear();
662             work->worklets.front()->output.ordinal = mOrdinal;
663             work->workletsProcessed = 1u;
664             work->result = C2_OK;
665             if (mBuffer) {
666                 work->worklets.front()->output.buffers.push_back(mBuffer);
667             }
668             ALOGV("timestamp = %lld, index = %lld, w/%s buffer", mOrdinal.timestamp.peekll(),
669                   mOrdinal.frameIndex.peekll(), mBuffer ? "" : "o");
670         }
671 
672       private:
673         const uint32_t mFlags;
674         const C2WorkOrdinalStruct mOrdinal;
675         const std::shared_ptr<C2Buffer> mBuffer;
676     };
677 
678     auto fillWork = [buffer](const std::unique_ptr<C2Work>& work) {
679         work->worklets.front()->output.flags = (C2FrameData::flags_t)0;
680         work->worklets.front()->output.buffers.clear();
681         work->worklets.front()->output.buffers.push_back(buffer);
682         work->worklets.front()->output.ordinal = work->input.ordinal;
683         work->workletsProcessed = 1u;
684     };
685 
686     if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
687         bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
688         // TODO: Check if cloneAndSend can be avoided by tracking number of frames remaining
689         if (eos) {
690             if (buffer) {
691                 mOutIndex = index;
692                 C2WorkOrdinalStruct outOrdinal = work->input.ordinal;
693                 cloneAndSend(mOutIndex, work,
694                              FillWork(C2FrameData::FLAG_INCOMPLETE, outOrdinal, buffer));
695                 buffer.reset();
696             }
697         } else {
698             fillWork(work);
699         }
700     } else {
701         finish(index, fillWork);
702     }
703 }
704 
copyBufferFromYUV420ToYV12(uint8_t * dstY,uint8_t * dstU,uint8_t * dstV,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 dstUStride,size_t dstVStride,uint32_t width,uint32_t height)705 static void copyBufferFromYUV420ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV,
706                                        const uint8_t* srcY, const uint8_t* srcU,
707                                        const uint8_t* srcV, size_t srcYStride, size_t srcUStride,
708                                        size_t srcVStride, size_t dstYStride, size_t dstUStride,
709                                        size_t dstVStride, uint32_t width, uint32_t height) {
710     for (size_t i = 0; i < height; ++i) {
711         memcpy(dstY, srcY, width);
712         srcY += srcYStride;
713         dstY += dstYStride;
714     }
715 
716     for (size_t i = 0; i < height / 2; ++i) {
717         memcpy(dstU, srcU, width / 2);
718         memcpy(dstV, srcV, width / 2);
719         dstU += dstUStride;
720         srcU += srcUStride;
721         dstV += dstVStride;
722         srcV += srcVStride;
723     }
724 }
725 
copyBufferP210(uint16_t * dstY,uint16_t * dstUV,const uint16_t * srcY,const uint16_t * srcUV,size_t srcYStride,size_t srcUVStride,size_t dstYStride,size_t dstUVStride,size_t width,size_t height)726 static void copyBufferP210(uint16_t *dstY, uint16_t *dstUV, const uint16_t *srcY,
727             const uint16_t *srcUV, size_t srcYStride, size_t srcUVStride, size_t dstYStride,
728             size_t dstUVStride, size_t width, size_t height) {
729     for (size_t y = 0; y < height; ++y) {
730         memcpy(dstY, srcY, width * sizeof(uint16_t));
731         srcY += srcYStride;
732         dstY += dstYStride;
733     }
734 
735     for (size_t y = 0; y < height; ++y) {
736         memcpy(dstUV, srcUV, width * sizeof(uint16_t));
737         srcUV += srcUVStride;
738         dstUV += dstUVStride;
739     }
740 }
741 
copyBufferFromYUV422ToYV12(uint8_t * dstY,uint8_t * dstU,uint8_t * dstV,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 dstUStride,size_t dstVStride,uint32_t width,uint32_t height)742 static void copyBufferFromYUV422ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV,
743                                        const uint8_t* srcY, const uint8_t* srcU,
744                                        const uint8_t* srcV, size_t srcYStride, size_t srcUStride,
745                                        size_t srcVStride, size_t dstYStride, size_t dstUStride,
746                                        size_t dstVStride, uint32_t width, uint32_t height) {
747     for (size_t i = 0; i < height; ++i) {
748         memcpy(dstY, srcY, width);
749         srcY += srcYStride;
750         dstY += dstYStride;
751     }
752 
753     for (size_t i = 0; i < height / 2; ++i) {
754         memcpy(dstU, srcU, width / 2);
755         memcpy(dstV, srcV, width / 2);
756         dstU += dstUStride;
757         srcU += srcUStride * 2;
758         dstV += dstVStride;
759         srcV += srcVStride * 2;
760     }
761 }
762 
copyBufferFromYUV42010bitToP010(uint16_t * dstY,uint16_t * dstUV,const uint16_t * srcY,const uint16_t * srcU,const uint16_t * srcV,size_t srcYStride,size_t srcUStride,size_t srcVStride,size_t dstYStride,size_t dstUVStride,size_t width,size_t height)763 static void copyBufferFromYUV42010bitToP010(uint16_t* dstY, uint16_t* dstUV, const uint16_t* srcY,
764                                             const uint16_t* srcU, const uint16_t* srcV,
765                                             size_t srcYStride, size_t srcUStride, size_t srcVStride,
766                                             size_t dstYStride, size_t dstUVStride, size_t width,
767                                             size_t height) {
768     for (size_t y = 0; y < height; ++y) {
769         for (size_t x = 0; x < width; ++x) {
770             dstY[x] = srcY[x] << 6;
771         }
772         srcY += srcYStride;
773         dstY += dstYStride;
774     }
775 
776     for (size_t y = 0; y < height / 2; ++y) {
777         for (size_t x = 0; x < width / 2; ++x) {
778             dstUV[2 * x] = srcU[x] << 6;
779             dstUV[2 * x + 1] = srcV[x] << 6;
780         }
781         srcU += srcUStride;
782         srcV += srcVStride;
783         dstUV += dstUVStride;
784     }
785 }
786 
copyBufferFromYUV42210bitToP010(uint16_t * dstY,uint16_t * dstUV,const uint16_t * srcY,const uint16_t * srcU,const uint16_t * srcV,size_t srcYStride,size_t srcUStride,size_t srcVStride,size_t dstYStride,size_t dstUVStride,size_t width,size_t height)787 static void copyBufferFromYUV42210bitToP010(uint16_t* dstY, uint16_t* dstUV, const uint16_t* srcY,
788                                             const uint16_t* srcU, const uint16_t* srcV,
789                                             size_t srcYStride, size_t srcUStride, size_t srcVStride,
790                                             size_t dstYStride, size_t dstUVStride, size_t width,
791                                             size_t height) {
792     for (size_t y = 0; y < height; ++y) {
793         for (size_t x = 0; x < width; ++x) {
794             dstY[x] = srcY[x] << 6;
795         }
796         srcY += srcYStride;
797         dstY += dstYStride;
798     }
799 
800     for (size_t y = 0; y < height / 2; ++y) {
801         for (size_t x = 0; x < width / 2; ++x) {
802             dstUV[2 * x] = srcU[x] << 6;
803             dstUV[2 * x + 1] = srcV[x] << 6;
804         }
805         srcU += srcUStride * 2;
806         srcV += srcVStride * 2;
807         dstUV += dstUVStride;
808     }
809 }
810 
copyBufferFromP210ToP010(uint16_t * dstY,uint16_t * dstUV,const uint16_t * srcY,const uint16_t * srcUV,size_t srcYStride,size_t srcUVStride,size_t dstYStride,size_t dstUVStride,size_t width,size_t height)811 static void copyBufferFromP210ToP010(uint16_t* dstY, uint16_t* dstUV, const uint16_t* srcY,
812                                      const uint16_t* srcUV, size_t srcYStride, size_t srcUVStride,
813                                      size_t dstYStride, size_t dstUVStride, size_t width,
814                                      size_t height) {
815     for (size_t y = 0; y < height; ++y) {
816         memcpy(dstY, srcY, width * sizeof(uint16_t));
817         srcY += srcYStride;
818         dstY += dstYStride;
819     }
820 
821     for (size_t y = 0; y < height / 2; ++y) {
822         memcpy(dstUV, srcUV, width * 2);
823         srcUV += srcUVStride * 2;
824         dstUV += dstUVStride;
825     }
826 }
827 
copyBufferFromYUV42010bitToYV12(uint8_t * dstY,uint8_t * dstU,uint8_t * dstV,const uint16_t * srcY,const uint16_t * srcU,const uint16_t * srcV,size_t srcYStride,size_t srcUStride,size_t srcVStride,size_t dstYStride,size_t dstUStride,size_t dstVStride,uint32_t width,uint32_t height)828 static void copyBufferFromYUV42010bitToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV,
829                                             const uint16_t* srcY, const uint16_t* srcU,
830                                             const uint16_t* srcV, size_t srcYStride,
831                                             size_t srcUStride, size_t srcVStride, size_t dstYStride,
832                                             size_t dstUStride, size_t dstVStride, uint32_t width,
833                                             uint32_t height) {
834     for (size_t i = 0; i < height; ++i) {
835         for (size_t j = 0; j < width; ++j) {
836             dstY[i * dstYStride + j] = (srcY[i * srcYStride + j] >> 2) & 0xFF;
837         }
838     }
839 
840     for (size_t i = 0; i < height / 2; ++i) {
841         for (size_t j = 0; j < width / 2; ++j) {
842             dstU[i * dstUStride + j] = (srcU[i * srcUStride + j] >> 2) & 0xFF;
843         }
844     }
845 
846     for (size_t i = 0; i < height / 2; ++i) {
847         for (size_t j = 0; j < width / 2; ++j) {
848             dstV[i * dstVStride + j] = (srcV[i * srcVStride + j] >> 2) & 0xFF;
849         }
850     }
851 }
852 
copyBufferFromYUV42210bitToYV12(uint8_t * dstY,uint8_t * dstU,uint8_t * dstV,const uint16_t * srcY,const uint16_t * srcU,const uint16_t * srcV,size_t srcYStride,size_t srcUStride,size_t srcVStride,size_t dstYStride,size_t dstUStride,size_t dstVStride,uint32_t width,uint32_t height)853 static void copyBufferFromYUV42210bitToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV,
854                                             const uint16_t* srcY, const uint16_t* srcU,
855                                             const uint16_t* srcV, size_t srcYStride,
856                                             size_t srcUStride, size_t srcVStride, size_t dstYStride,
857                                             size_t dstUStride, size_t dstVStride, uint32_t width,
858                                             uint32_t height) {
859     for (size_t i = 0; i < height; ++i) {
860         for (size_t j = 0; j < width; ++j) {
861             dstY[i * dstYStride + j] = (srcY[i * srcYStride + j] >> 2) & 0xFF;
862         }
863     }
864 
865     for (size_t i = 0; i < height / 2; ++i) {
866         for (size_t j = 0; j < width / 2; ++j) {
867             dstU[i * dstUStride + j] = (srcU[i * srcUStride * 2 + j] >> 2) & 0xFF;
868         }
869     }
870 
871     for (size_t i = 0; i < height / 2; ++i) {
872         for (size_t j = 0; j < width / 2; ++j) {
873             dstV[i * dstVStride + j] = (srcV[i * srcVStride * 2 + j] >> 2) & 0xFF;
874         }
875     }
876 }
877 
copyBufferFromP210ToYV12(uint8_t * dstY,uint8_t * dstU,uint8_t * dstV,const uint16_t * srcY,const uint16_t * srcUV,size_t srcYStride,size_t srcUVStride,size_t dstYStride,size_t dstUStride,size_t dstVStride,size_t width,size_t height)878 static void copyBufferFromP210ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV,
879                                      const uint16_t* srcY, const uint16_t* srcUV, size_t srcYStride,
880                                      size_t srcUVStride, size_t dstYStride, size_t dstUStride,
881                                      size_t dstVStride, size_t width, size_t height) {
882     for (size_t i = 0; i < height; ++i) {
883         for (size_t j = 0; j < width; ++j) {
884             dstY[i * dstYStride + j] = (srcY[i * srcYStride + j] >> 8) & 0xFF;
885         }
886     }
887 
888     for (size_t i = 0; i < height / 2; ++i) {
889         for (size_t j = 0; j < width / 2; ++j) {
890             dstV[i * dstVStride + j] = (srcUV[i * srcUVStride * 2 + j * 2] >> 8) & 0xFF;
891             dstU[i * dstUStride + j] = (srcUV[i * srcUVStride * 2 + j * 2 + 1] >> 8) & 0xFF;
892         }
893     }
894 }
895 
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)896 void C2SoftApvDec::process(const std::unique_ptr<C2Work>& work,
897                            const std::shared_ptr<C2BlockPool>& pool) {
898     // Initialize output work
899     work->result = C2_OK;
900     work->workletsProcessed = 0u;
901     work->worklets.front()->output.configUpdate.clear();
902     work->worklets.front()->output.flags = work->input.flags;
903     if (mSignalledError || mSignalledOutputEos) {
904         work->result = C2_BAD_VALUE;
905         return;
906     }
907 
908     int ret = 0;
909     size_t inOffset = 0u;
910     size_t inSize = 0u;
911     C2ReadView rView = mDummyReadView;
912     if (!work->input.buffers.empty()) {
913         rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
914         inSize = rView.capacity();
915         if (inSize && rView.error()) {
916             ALOGE("read view map failed %d", rView.error());
917             work->result = C2_CORRUPTED;
918             return;
919         }
920     }
921 
922     bool codecConfig = ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0);
923     bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
924 
925     ALOGV("in buffer attr. size %zu timestamp %llu frameindex %d, flags %x", inSize,
926           work->input.ordinal.timestamp.peekull(), (int)work->input.ordinal.frameIndex.peeku(),
927           work->input.flags);
928 
929     if (codecConfig) {
930         fillEmptyWork(work);
931         return;
932     }
933 
934     if (inSize > 0) {
935         uint8_t* bitstream = const_cast<uint8_t*>(rView.data() + inOffset);
936         oapv_au_info_t aui;
937         oapv_bitb_t bitb;
938         bitb.addr = bitstream + 4;  // skip au
939         bitb.ssize = inSize - 4;
940 
941         if (OAPV_FAILED(oapvd_info(bitb.addr, bitb.ssize, &aui))) {
942             ALOGE("cannot get information from bitstream");
943             return;
944         }
945 
946         /* create decoding frame buffers */
947         ofrms.num_frms = aui.num_frms;
948         if (ofrms.num_frms <= 0) {
949             ALOGE("Parse error - no output frame(%d)", ofrms.num_frms);
950             fillEmptyWork(work);
951             return;
952         }
953         for (int i = 0; i < ofrms.num_frms; i++) {
954             oapv_frm_info_t* finfo = &aui.frm_info[FRM_IDX];
955             oapv_frm_t* frm = &ofrms.frm[i];
956 
957             if (mWidth != finfo->w || mHeight != finfo->w) {
958                 mWidth = finfo->w;
959                 mHeight = finfo->h;
960             }
961 
962             if (frm->imgb != NULL && (frm->imgb->w[0] != finfo->w || frm->imgb->h[0] != finfo->h)) {
963                 frm->imgb->release(frm->imgb);
964                 frm->imgb = NULL;
965             }
966 
967             if (frm->imgb == NULL) {
968                 if (outputCsp == OUTPUT_CSP_P210) {
969                     frm->imgb = imgb_create(finfo->w, finfo->h, OAPV_CS_P210);
970                 } else {
971                     frm->imgb = imgb_create(finfo->w, finfo->h, finfo->cs);
972                 }
973                 if (frm->imgb == NULL) {
974                     ALOGE("cannot allocate image buffer (w:%d, h:%d, cs:%d)", finfo->w, finfo->h,
975                           finfo->cs);
976                     fillEmptyWork(work);
977                     return;
978                 }
979             }
980         }
981 
982         oapvd_stat_t stat;
983         ret = oapvd_decode(oapvdHandle, &bitb, &ofrms, oapvmHandle, &stat);
984         if (bitb.ssize != stat.read) {
985             ALOGW("decode done, input size: %d, processed size: %d", bitb.ssize, stat.read);
986         }
987 
988         if (OAPV_FAILED(ret)) {
989             ALOGE("failed to decode bitstream\n");
990             fillEmptyWork(work);
991             return;
992         }
993 
994         status_t err = outputBuffer(pool, work);
995         if (err == NOT_ENOUGH_DATA) {
996             if (inSize > 0) {
997                 ALOGV("Maybe non-display frame at %lld.", work->input.ordinal.frameIndex.peekll());
998                 // send the work back with empty buffer.
999                 inSize = 0;
1000             }
1001         } else if (err != OK) {
1002             ALOGD("Error while getting the output frame out");
1003             // work->result would be already filled; do fillEmptyWork() below to
1004             // send the work back.
1005             inSize = 0;
1006         }
1007     }
1008 
1009     if (eos) {
1010         drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
1011         mSignalledOutputEos = true;
1012     } else if (!inSize) {
1013         fillEmptyWork(work);
1014     }
1015 }
1016 
getVuiParams(VuiColorAspects * buffer)1017 void C2SoftApvDec::getVuiParams(VuiColorAspects* buffer) {
1018     VuiColorAspects vuiColorAspects;
1019     vuiColorAspects.primaries = buffer->primaries;
1020     vuiColorAspects.transfer = buffer->transfer;
1021     vuiColorAspects.coeffs = buffer->coeffs;
1022     vuiColorAspects.fullRange = buffer->fullRange;
1023 
1024     // convert vui aspects to C2 values if changed
1025     if (!(vuiColorAspects == mBitstreamColorAspects)) {
1026         mBitstreamColorAspects = vuiColorAspects;
1027         ColorAspects sfAspects;
1028         C2StreamColorAspectsInfo::input codedAspects = { 0u };
1029         ColorUtils::convertIsoColorAspectsToCodecAspects(
1030                 vuiColorAspects.primaries, vuiColorAspects.transfer, vuiColorAspects.coeffs,
1031                 vuiColorAspects.fullRange, sfAspects);
1032         if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) {
1033             codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED;
1034         }
1035         if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) {
1036             codedAspects.range = C2Color::RANGE_UNSPECIFIED;
1037         }
1038         if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) {
1039             codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED;
1040         }
1041         if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) {
1042             codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED;
1043         }
1044         ALOGV("colorAspects: primaries:%d, transfer:%d, coeffs:%d, fullRange:%d",
1045                 codedAspects.primaries, codedAspects.transfer, codedAspects.matrix,
1046                 codedAspects.range);
1047         std::vector<std::unique_ptr<C2SettingResult>> failures;
1048         mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures);
1049     }
1050 }
1051 
outputBuffer(const std::shared_ptr<C2BlockPool> & pool,const std::unique_ptr<C2Work> & work)1052 status_t C2SoftApvDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
1053                                     const std::unique_ptr<C2Work>& work) {
1054     if (!(work && pool)) return BAD_VALUE;
1055 
1056     oapv_imgb_t* imgbOutput = nullptr;
1057     std::shared_ptr<C2GraphicBlock> block;
1058 
1059     if (ofrms.num_frms > 0) {
1060         for(int i = 0; i < ofrms.num_frms; i++) {
1061             oapv_frm_t* frm = &ofrms.frm[0];
1062             if(frm->pbu_type == OAPV_PBU_TYPE_PRIMARY_FRAME) {
1063                 imgbOutput = frm->imgb;
1064                 break;
1065             }
1066         }
1067         if(imgbOutput == nullptr) {
1068             ALOGW("No OAPV primary frame");
1069             return false;
1070         }
1071     } else {
1072         ALOGW("No output frames");
1073         return false;
1074     }
1075     bool isMonochrome = OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CS_YCBCR400;
1076 
1077     // TODO: use bitstream color aspect after vui parsing
1078     VuiColorAspects colorAspect;
1079     colorAspect.primaries = 2;
1080     colorAspect.transfer = 2;
1081     colorAspect.coeffs = 2;
1082     colorAspect.fullRange = 1;
1083     getVuiParams(&colorAspect);
1084 
1085     uint32_t format = HAL_PIXEL_FORMAT_YV12;
1086     std::shared_ptr<C2StreamColorAspectsInfo::output> codedColorAspects;
1087     if (OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs) == 10 &&
1088         mPixelFormatInfo->value != HAL_PIXEL_FORMAT_YCBCR_420_888) {
1089         IntfImpl::Lock lock = mIntf->lock();
1090         codedColorAspects = mIntf->getColorAspects_l();
1091 
1092         bool allowRGBA1010102 = false;
1093         if (codedColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
1094             codedColorAspects->matrix == C2Color::MATRIX_BT2020 &&
1095             codedColorAspects->transfer == C2Color::TRANSFER_ST2084) {
1096             allowRGBA1010102 = true;
1097         }
1098         format = getHalPixelFormatForBitDepth10(allowRGBA1010102);
1099     }
1100 
1101     if (mHalPixelFormat != format) {
1102         C2StreamPixelFormatInfo::output pixelFormat(0u, format);
1103         std::vector<std::unique_ptr<C2SettingResult>> failures;
1104         c2_status_t err = mIntf->config({&pixelFormat}, C2_MAY_BLOCK, &failures);
1105         if (err == C2_OK) {
1106             work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(pixelFormat));
1107         } else {
1108             ALOGE("Config update pixelFormat failed");
1109             mSignalledError = true;
1110             work->workletsProcessed = 1u;
1111             work->result = C2_CORRUPTED;
1112             return UNKNOWN_ERROR;
1113         }
1114         mHalPixelFormat = format;
1115     }
1116     ALOGV("mHalPixelFormat: %u, format: %d", mHalPixelFormat, format);
1117 
1118     C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
1119 
1120     // check. align height to 2 times does not work.
1121     c2_status_t err =
1122             pool->fetchGraphicBlock(align(mWidth, 16), align(mHeight, 16), format, usage, &block);
1123 
1124     if (err != C2_OK) {
1125         ALOGE("fetchGraphicBlock for Output failed with status %d", err);
1126         work->result = err;
1127         return false;
1128     }
1129 
1130     C2GraphicView wView = block->map().get();
1131     if (wView.error()) {
1132         ALOGE("graphic view map failed %d", wView.error());
1133         work->result = C2_CORRUPTED;
1134         return false;
1135     }
1136 
1137     ALOGV("provided (%dx%d) required (%dx%d)", block->width(), block->height(), mWidth, mHeight);
1138 
1139     uint8_t* dstY = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_Y]);
1140     uint8_t* dstU = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_U]);
1141     uint8_t* dstV = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_V]);
1142 
1143     C2PlanarLayout layout = wView.layout();
1144     size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
1145     size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
1146     size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
1147 
1148     if(format == AHARDWAREBUFFER_FORMAT_YCbCr_P210) {
1149         if(OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs) == 10) {
1150             const uint16_t *srcY = (const uint16_t *)imgbOutput->a[0];
1151             const uint16_t *srcU = (const uint16_t *)imgbOutput->a[1];
1152             const uint16_t *srcV = (const uint16_t *)imgbOutput->a[2];
1153             size_t srcYStride = imgbOutput->s[0] / 2;
1154             size_t srcUStride = imgbOutput->s[1] / 2;
1155             size_t srcVStride = imgbOutput->s[2] / 2;
1156             dstYStride /= 2;
1157             dstUStride /= 2;
1158             dstVStride /= 2;
1159             ALOGV("OAPV_CS_P210 buffer");
1160             copyBufferP210((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU,
1161                             srcYStride, srcUStride, dstYStride, dstUStride, mWidth, mHeight);
1162         } else {
1163             ALOGE("Not supported convder from bd:%d, format: %d(%s), to format: %d(%s)",
1164                 OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs),
1165                 OAPV_CS_GET_FORMAT(imgbOutput->cs),
1166                 OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR420 ?
1167                     "YUV420" : (OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR422 ?
1168                                  "YUV422" : "UNKNOWN"),
1169                 format,
1170                 format == HAL_PIXEL_FORMAT_YCBCR_P010 ?
1171                     "P010" : (format == HAL_PIXEL_FORMAT_YCBCR_420_888 ?
1172                          "YUV420" : (format == HAL_PIXEL_FORMAT_YV12 ? "YV12" : "UNKNOWN"))
1173                 );
1174         }
1175     } else if(format == HAL_PIXEL_FORMAT_YCBCR_P010) {
1176         if (OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs) == 10) {
1177             const uint16_t* srcY = (const uint16_t*)imgbOutput->a[0];
1178             const uint16_t* srcU = (const uint16_t*)imgbOutput->a[1];
1179             const uint16_t* srcV = (const uint16_t*)imgbOutput->a[2];
1180             size_t srcYStride = imgbOutput->s[0] / 2;
1181             size_t srcUStride = imgbOutput->s[1] / 2;
1182             size_t srcVStride = imgbOutput->s[2] / 2;
1183             dstYStride /= 2;
1184             dstUStride /= 2;
1185             dstVStride /= 2;
1186             if (OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR420) {
1187                 ALOGV("OAPV_CS_YUV420 10bit to P010");
1188                 copyBufferFromYUV42010bitToP010((uint16_t*)dstY, (uint16_t*)dstU, srcY, srcU, srcV,
1189                                                 srcYStride, srcUStride, srcVStride, dstYStride,
1190                                                 dstUStride, mWidth, mHeight);
1191             } else if (OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR422) {
1192                 ALOGV("OAPV_CS_YUV422 10bit to P010");
1193                 copyBufferFromYUV42210bitToP010((uint16_t*)dstY, (uint16_t*)dstU, srcY, srcU, srcV,
1194                                                 srcYStride, srcUStride, srcVStride, dstYStride,
1195                                                 dstUStride, mWidth, mHeight);
1196             } else if (OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_PLANAR2) {
1197                 ALOGV("OAPV_CS_P210 to P010");
1198                 copyBufferFromP210ToP010((uint16_t*)dstY, (uint16_t*)dstU, srcY, srcU, srcYStride,
1199                                          srcUStride, dstYStride, dstUStride, mWidth, mHeight);
1200             } else {
1201                 ALOGE("Not supported convert format : %d", OAPV_CS_GET_FORMAT(imgbOutput->cs));
1202             }
1203         } else {
1204             ALOGE("Not supported convder from bd:%d, format: %d(%s), to format: %d(%s)",
1205                   OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs), OAPV_CS_GET_FORMAT(imgbOutput->cs),
1206                   OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR420
1207                           ? "YUV420"
1208                           : (OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR422 ? "YUV422"
1209                                                                                     : "UNKNOWN"),
1210                   format,
1211                   format == HAL_PIXEL_FORMAT_YCBCR_P010
1212                           ? "P010"
1213                           : (format == HAL_PIXEL_FORMAT_YCBCR_420_888
1214                                      ? "YUV420"
1215                                      : (format == HAL_PIXEL_FORMAT_YV12 ? "YV12" : "UNKNOWN")));
1216         }
1217     } else {  // HAL_PIXEL_FORMAT_YV12
1218         if (OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs) == 10) {
1219             const uint16_t* srcY = (const uint16_t*)imgbOutput->a[0];
1220             const uint16_t* srcV = (const uint16_t*)imgbOutput->a[1];
1221             const uint16_t* srcU = (const uint16_t*)imgbOutput->a[2];
1222             size_t srcYStride = imgbOutput->s[0] / 2;
1223             size_t srcVStride = imgbOutput->s[1] / 2;
1224             size_t srcUStride = imgbOutput->s[2] / 2;
1225             if (OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR420) {
1226                 ALOGV("OAPV_CS_YUV420 10bit to YV12");
1227                 copyBufferFromYUV42010bitToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride,
1228                                                 srcUStride, srcVStride, dstYStride, dstUStride,
1229                                                 dstVStride, mWidth, mHeight);
1230             } else if (OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR422) {
1231                 ALOGV("OAPV_CS_YUV422 10bit to YV12");
1232                 copyBufferFromYUV42210bitToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride,
1233                                                 srcUStride, srcVStride, dstYStride, dstUStride,
1234                                                 dstVStride, mWidth, mHeight);
1235             } else if (OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_PLANAR2) {
1236                 ALOGV("OAPV_CS_P210 to YV12");
1237                 copyBufferFromP210ToYV12(dstY, dstU, dstV, srcY, srcV, srcYStride, srcVStride,
1238                                          dstYStride, dstUStride, dstVStride, mWidth, mHeight);
1239             } else {
1240                 ALOGE("Not supported convert format : %d", OAPV_CS_GET_FORMAT(imgbOutput->cs));
1241             }
1242         } else if (OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs) == 8) {
1243             const uint8_t* srcY = (const uint8_t*)imgbOutput->a[0];
1244             const uint8_t* srcV = (const uint8_t*)imgbOutput->a[1];
1245             const uint8_t* srcU = (const uint8_t*)imgbOutput->a[2];
1246             size_t srcYStride = imgbOutput->s[0];
1247             size_t srcVStride = imgbOutput->s[1];
1248             size_t srcUStride = imgbOutput->s[2];
1249             if (OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR420) {
1250                 ALOGV("OAPV_CS_YUV420 to YV12");
1251                 copyBufferFromYUV420ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride,
1252                                            srcUStride, srcVStride, dstYStride, dstUStride,
1253                                            dstVStride, mWidth, mHeight);
1254             } else if (OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR422) {
1255                 ALOGV("OAPV_CS_YUV422 to YV12");
1256                 copyBufferFromYUV422ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride,
1257                                            srcUStride, srcVStride, dstYStride, dstUStride,
1258                                            dstVStride, mWidth, mHeight);
1259             } else {
1260                 ALOGE("Not supported convert format : %d", OAPV_CS_GET_FORMAT(imgbOutput->cs));
1261             }
1262         } else {
1263             ALOGE("Not supported convert from bd:%d, format: %d(%s), to format: %d(%s)",
1264                   OAPV_CS_GET_BIT_DEPTH(imgbOutput->cs), OAPV_CS_GET_FORMAT(imgbOutput->cs),
1265                   OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR420
1266                           ? "YUV420"
1267                           : (OAPV_CS_GET_FORMAT(imgbOutput->cs) == OAPV_CF_YCBCR422 ? "YUV422"
1268                                                                                     : "UNKNOWN"),
1269                   format,
1270                   format == HAL_PIXEL_FORMAT_YCBCR_P010
1271                           ? "P010"
1272                           : (format == HAL_PIXEL_FORMAT_YCBCR_420_888
1273                                      ? "YUV420"
1274                                      : (format == HAL_PIXEL_FORMAT_YV12 ? "YV12" : "UNKNOWN")));
1275         }
1276     }
1277 
1278     finishWork(work->input.ordinal.frameIndex.peekll(), work, std::move(block));
1279     return OK;
1280 }
1281 
drainInternal(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool,const std::unique_ptr<C2Work> & work)1282 c2_status_t C2SoftApvDec::drainInternal(uint32_t drainMode,
1283                                         const std::shared_ptr<C2BlockPool>& pool,
1284                                         const std::unique_ptr<C2Work>& work) {
1285     if (drainMode == NO_DRAIN) {
1286         ALOGW("drain with NO_DRAIN: no-op");
1287         return C2_OK;
1288     }
1289     if (drainMode == DRAIN_CHAIN) {
1290         ALOGW("DRAIN_CHAIN not supported");
1291         return C2_OMITTED;
1292     }
1293 
1294     if (drainMode == DRAIN_COMPONENT_WITH_EOS && work && work->workletsProcessed == 0u) {
1295         fillEmptyWork(work);
1296     }
1297     return C2_OK;
1298 }
1299 
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)1300 c2_status_t C2SoftApvDec::drain(uint32_t drainMode, const std::shared_ptr<C2BlockPool>& pool) {
1301     return drainInternal(drainMode, pool, nullptr);
1302 }
1303 
1304 class C2SoftApvDecFactory : public C2ComponentFactory {
1305   public:
C2SoftApvDecFactory()1306     C2SoftApvDecFactory()
1307         : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
1308                   GetCodec2PlatformComponentStore()->getParamReflector())) {}
1309 
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)1310     virtual c2_status_t createComponent(c2_node_id_t id,
1311                                         std::shared_ptr<C2Component>* const component,
1312                                         std::function<void(C2Component*)> deleter) override {
1313         *component = std::shared_ptr<C2Component>(
1314                 new C2SoftApvDec(COMPONENT_NAME, id,
1315                                  std::make_shared<C2SoftApvDec::IntfImpl>(mHelper)),
1316                 deleter);
1317         return C2_OK;
1318     }
1319 
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)1320     virtual c2_status_t createInterface(
1321             c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
1322             std::function<void(C2ComponentInterface*)> deleter) override {
1323         *interface = std::shared_ptr<C2ComponentInterface>(
1324                 new SimpleInterface<C2SoftApvDec::IntfImpl>(
1325                         COMPONENT_NAME, id, std::make_shared<C2SoftApvDec::IntfImpl>(mHelper)),
1326                 deleter);
1327         return C2_OK;
1328     }
1329 
1330     virtual ~C2SoftApvDecFactory() override = default;
1331 
1332   private:
1333     std::shared_ptr<C2ReflectorHelper> mHelper;
1334 };
1335 
1336 }  // namespace android
1337 
CreateCodec2Factory()1338 __attribute__((cfi_canonical_jump_table)) extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
1339     if (!android::media::swcodec::flags::apv_software_codec()) {
1340         ALOGV("APV SW Codec is not enabled");
1341         return nullptr;
1342     }
1343     return new ::android::C2SoftApvDecFactory();
1344 }
1345 
DestroyCodec2Factory(::C2ComponentFactory * factory)1346 __attribute__((cfi_canonical_jump_table)) extern "C" void DestroyCodec2Factory(
1347         ::C2ComponentFactory* factory) {
1348     delete factory;
1349 }
1350