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