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