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