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