blob: d234f21f96204c7e80e9b06e09ddc8518427235d [file] [log] [blame]
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -07001/*
2 * Copyright (C) 2019 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 "C2SoftGav1Dec"
19#include "C2SoftGav1Dec.h"
20
21#include <C2Debug.h>
22#include <C2PlatformSupport.h>
Harish Mahendrakarf0fa7a22021-12-10 20:36:32 -080023#include <Codec2BufferUtils.h>
Harish Mahendrakarf5dec502022-04-13 15:53:55 -070024#include <Codec2CommonUtils.h>
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +053025#include <Codec2Mapper.h>
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -070026#include <SimpleC2Interface.h>
27#include <log/log.h>
28#include <media/stagefright/foundation/AUtils.h>
29#include <media/stagefright/foundation/MediaDefs.h>
30
31namespace android {
32
Ray Essickc2cc4372019-08-21 14:02:28 -070033// codecname set and passed in as a compile flag from Android.bp
34constexpr char COMPONENT_NAME[] = CODECNAME;
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -070035
Ray Essick1af2cc52022-01-25 15:59:23 -080036constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
37
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -070038class C2SoftGav1Dec::IntfImpl : public SimpleInterface<void>::BaseParams {
39 public:
40 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
41 : SimpleInterface<void>::BaseParams(
42 helper, COMPONENT_NAME, C2Component::KIND_DECODER,
43 C2Component::DOMAIN_VIDEO, MEDIA_MIMETYPE_VIDEO_AV1) {
44 noPrivateBuffers(); // TODO: account for our buffers here.
45 noInputReferences();
46 noOutputReferences();
47 noInputLatency();
48 noTimeStretch();
49
50 addParameter(DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
51 .withConstValue(new C2ComponentAttributesSetting(
52 C2Component::ATTRIB_IS_TEMPORAL))
53 .build());
54
55 addParameter(
56 DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
57 .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
58 .withFields({
Vignesh Venkatasubramanianc4d385f2022-02-22 10:49:46 -080059 C2F(mSize, width).inRange(2, 4096),
60 C2F(mSize, height).inRange(2, 4096),
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -070061 })
62 .withSetter(SizeSetter)
63 .build());
64
65 addParameter(DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
66 .withDefault(new C2StreamProfileLevelInfo::input(
67 0u, C2Config::PROFILE_AV1_0, C2Config::LEVEL_AV1_2_1))
68 .withFields({C2F(mProfileLevel, profile)
69 .oneOf({C2Config::PROFILE_AV1_0,
70 C2Config::PROFILE_AV1_1}),
71 C2F(mProfileLevel, level)
72 .oneOf({
Harish Mahendrakar1ad8c3b2021-06-04 15:42:31 -070073 C2Config::LEVEL_AV1_2, C2Config::LEVEL_AV1_2_1,
74 C2Config::LEVEL_AV1_2_2, C2Config::LEVEL_AV1_2_3,
75 C2Config::LEVEL_AV1_3, C2Config::LEVEL_AV1_3_1,
76 C2Config::LEVEL_AV1_3_2, C2Config::LEVEL_AV1_3_3,
77 C2Config::LEVEL_AV1_4, C2Config::LEVEL_AV1_4_1,
78 C2Config::LEVEL_AV1_4_2, C2Config::LEVEL_AV1_4_3,
79 C2Config::LEVEL_AV1_5, C2Config::LEVEL_AV1_5_1,
80 C2Config::LEVEL_AV1_5_2, C2Config::LEVEL_AV1_5_3,
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -070081 })})
82 .withSetter(ProfileLevelSetter, mSize)
83 .build());
84
85 mHdr10PlusInfoInput = C2StreamHdr10PlusInfo::input::AllocShared(0);
86 addParameter(
87 DefineParam(mHdr10PlusInfoInput, C2_PARAMKEY_INPUT_HDR10_PLUS_INFO)
88 .withDefault(mHdr10PlusInfoInput)
89 .withFields({
90 C2F(mHdr10PlusInfoInput, m.value).any(),
91 })
92 .withSetter(Hdr10PlusInfoInputSetter)
93 .build());
94
95 mHdr10PlusInfoOutput = C2StreamHdr10PlusInfo::output::AllocShared(0);
96 addParameter(
97 DefineParam(mHdr10PlusInfoOutput, C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO)
98 .withDefault(mHdr10PlusInfoOutput)
99 .withFields({
100 C2F(mHdr10PlusInfoOutput, m.value).any(),
101 })
102 .withSetter(Hdr10PlusInfoOutputSetter)
103 .build());
104
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530105 // default static info
106 C2HdrStaticMetadataStruct defaultStaticInfo{};
107 helper->addStructDescriptors<C2MasteringDisplayColorVolumeStruct, C2ColorXyStruct>();
108 addParameter(
109 DefineParam(mHdrStaticInfo, C2_PARAMKEY_HDR_STATIC_INFO)
110 .withDefault(new C2StreamHdrStaticInfo::output(0u, defaultStaticInfo))
111 .withFields({
112 C2F(mHdrStaticInfo, mastering.red.x).inRange(0, 1),
113 C2F(mHdrStaticInfo, mastering.red.y).inRange(0, 1),
114 C2F(mHdrStaticInfo, mastering.green.x).inRange(0, 1),
115 C2F(mHdrStaticInfo, mastering.green.y).inRange(0, 1),
116 C2F(mHdrStaticInfo, mastering.blue.x).inRange(0, 1),
117 C2F(mHdrStaticInfo, mastering.blue.y).inRange(0, 1),
118 C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
119 C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
120 C2F(mHdrStaticInfo, mastering.maxLuminance).inRange(0, 65535),
121 C2F(mHdrStaticInfo, mastering.minLuminance).inRange(0, 6.5535),
122 C2F(mHdrStaticInfo, maxCll).inRange(0, 0XFFFF),
123 C2F(mHdrStaticInfo, maxFall).inRange(0, 0XFFFF)
124 })
125 .withSetter(HdrStaticInfoSetter)
126 .build());
127
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700128 addParameter(
129 DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
130 .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240))
131 .withFields({
132 C2F(mSize, width).inRange(2, 2048, 2),
133 C2F(mSize, height).inRange(2, 2048, 2),
134 })
135 .withSetter(MaxPictureSizeSetter, mSize)
136 .build());
137
138 addParameter(DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
Ray Essick1af2cc52022-01-25 15:59:23 -0800139 .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700140 .withFields({
141 C2F(mMaxInputSize, value).any(),
142 })
143 .calculatedAs(MaxInputSizeSetter, mMaxSize)
144 .build());
145
146 C2ChromaOffsetStruct locations[1] = {C2ChromaOffsetStruct::ITU_YUV_420_0()};
147 std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
148 C2StreamColorInfo::output::AllocShared(1u, 0u, 8u /* bitDepth */,
149 C2Color::YUV_420);
150 memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
151
152 defaultColorInfo = C2StreamColorInfo::output::AllocShared(
153 {C2ChromaOffsetStruct::ITU_YUV_420_0()}, 0u, 8u /* bitDepth */,
154 C2Color::YUV_420);
155 helper->addStructDescriptors<C2ChromaOffsetStruct>();
156
157 addParameter(DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
158 .withConstValue(defaultColorInfo)
159 .build());
160
161 addParameter(
162 DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
163 .withDefault(new C2StreamColorAspectsTuning::output(
164 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
165 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
166 .withFields(
167 {C2F(mDefaultColorAspects, range)
168 .inRange(C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
169 C2F(mDefaultColorAspects, primaries)
170 .inRange(C2Color::PRIMARIES_UNSPECIFIED,
171 C2Color::PRIMARIES_OTHER),
172 C2F(mDefaultColorAspects, transfer)
173 .inRange(C2Color::TRANSFER_UNSPECIFIED,
174 C2Color::TRANSFER_OTHER),
175 C2F(mDefaultColorAspects, matrix)
176 .inRange(C2Color::MATRIX_UNSPECIFIED,
177 C2Color::MATRIX_OTHER)})
178 .withSetter(DefaultColorAspectsSetter)
179 .build());
180
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530181 addParameter(
182 DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
183 .withDefault(new C2StreamColorAspectsInfo::input(
184 0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
185 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
186 .withFields({
187 C2F(mCodedColorAspects, range).inRange(
188 C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
189 C2F(mCodedColorAspects, primaries).inRange(
190 C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
191 C2F(mCodedColorAspects, transfer).inRange(
192 C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
193 C2F(mCodedColorAspects, matrix).inRange(
194 C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
195 })
196 .withSetter(CodedColorAspectsSetter)
197 .build());
198
199 addParameter(
200 DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
201 .withDefault(new C2StreamColorAspectsInfo::output(
202 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
203 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
204 .withFields({
205 C2F(mColorAspects, range).inRange(
206 C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
207 C2F(mColorAspects, primaries).inRange(
208 C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
209 C2F(mColorAspects, transfer).inRange(
210 C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
211 C2F(mColorAspects, matrix).inRange(
212 C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
213 })
214 .withSetter(ColorAspectsSetter, mDefaultColorAspects, mCodedColorAspects)
215 .build());
216
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700217 std::vector<uint32_t> pixelFormats = {HAL_PIXEL_FORMAT_YCBCR_420_888};
Harish Mahendrakarf5dec502022-04-13 15:53:55 -0700218 if (isHalPixelFormatSupported((AHardwareBuffer_Format)HAL_PIXEL_FORMAT_YCBCR_P010)) {
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700219 pixelFormats.push_back(HAL_PIXEL_FORMAT_YCBCR_P010);
220 }
Harish Mahendrakar10c0c5d2022-05-30 20:35:16 -0700221 // If color format surface isn't added to supported formats, there is no way to know
222 // when the color-format is configured to surface. This is necessary to be able to
223 // choose 10-bit format while decoding 10-bit clips in surface mode.
224 pixelFormats.push_back(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
225
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700226 // TODO: support more formats?
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700227 addParameter(
228 DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
229 .withDefault(new C2StreamPixelFormatInfo::output(
230 0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
231 .withFields({C2F(mPixelFormat, value).oneOf(pixelFormats)})
232 .withSetter((Setter<decltype(*mPixelFormat)>::StrictValueWithNoDeps))
233 .build());
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700234 }
235
236 static C2R SizeSetter(bool mayBlock,
237 const C2P<C2StreamPictureSizeInfo::output> &oldMe,
238 C2P<C2StreamPictureSizeInfo::output> &me) {
239 (void)mayBlock;
240 C2R res = C2R::Ok();
241 if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
242 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
243 me.set().width = oldMe.v.width;
244 }
245 if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
246 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
247 me.set().height = oldMe.v.height;
248 }
249 return res;
250 }
251
252 static C2R MaxPictureSizeSetter(
253 bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output> &me,
254 const C2P<C2StreamPictureSizeInfo::output> &size) {
255 (void)mayBlock;
256 // TODO: get max width/height from the size's field helpers vs.
257 // hardcoding
258 me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4096u);
259 me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4096u);
260 return C2R::Ok();
261 }
262
263 static C2R MaxInputSizeSetter(
264 bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me,
265 const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
266 (void)mayBlock;
Ray Essick1af2cc52022-01-25 15:59:23 -0800267 // assume compression ratio of 2, but enforce a floor
268 me.set().value = c2_max((((maxSize.v.width + 63) / 64)
269 * ((maxSize.v.height + 63) / 64) * 3072), kMinInputBufferSize);
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700270 return C2R::Ok();
271 }
272
273 static C2R DefaultColorAspectsSetter(
274 bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) {
275 (void)mayBlock;
276 if (me.v.range > C2Color::RANGE_OTHER) {
277 me.set().range = C2Color::RANGE_OTHER;
278 }
279 if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
280 me.set().primaries = C2Color::PRIMARIES_OTHER;
281 }
282 if (me.v.transfer > C2Color::TRANSFER_OTHER) {
283 me.set().transfer = C2Color::TRANSFER_OTHER;
284 }
285 if (me.v.matrix > C2Color::MATRIX_OTHER) {
286 me.set().matrix = C2Color::MATRIX_OTHER;
287 }
288 return C2R::Ok();
289 }
290
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530291 static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) {
292 (void)mayBlock;
293 if (me.v.range > C2Color::RANGE_OTHER) {
294 me.set().range = C2Color::RANGE_OTHER;
295 }
296 if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
297 me.set().primaries = C2Color::PRIMARIES_OTHER;
298 }
299 if (me.v.transfer > C2Color::TRANSFER_OTHER) {
300 me.set().transfer = C2Color::TRANSFER_OTHER;
301 }
302 if (me.v.matrix > C2Color::MATRIX_OTHER) {
303 me.set().matrix = C2Color::MATRIX_OTHER;
304 }
305 return C2R::Ok();
306 }
307
308 static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
309 const C2P<C2StreamColorAspectsTuning::output> &def,
310 const C2P<C2StreamColorAspectsInfo::input> &coded) {
311 (void)mayBlock;
312 // take default values for all unspecified fields, and coded values for specified ones
313 me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range;
314 me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED
315 ? def.v.primaries : coded.v.primaries;
316 me.set().transfer = coded.v.transfer == TRANSFER_UNSPECIFIED
317 ? def.v.transfer : coded.v.transfer;
318 me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix : coded.v.matrix;
319 return C2R::Ok();
320 }
321
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700322 static C2R ProfileLevelSetter(
323 bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
324 const C2P<C2StreamPictureSizeInfo::output> &size) {
325 (void)mayBlock;
326 (void)size;
327 (void)me; // TODO: validate
328 return C2R::Ok();
329 }
330
331 std::shared_ptr<C2StreamColorAspectsTuning::output>
332 getDefaultColorAspects_l() {
333 return mDefaultColorAspects;
334 }
335
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530336 std::shared_ptr<C2StreamColorAspectsInfo::output> getColorAspects_l() {
337 return mColorAspects;
338 }
339
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700340 static C2R Hdr10PlusInfoInputSetter(bool mayBlock,
341 C2P<C2StreamHdr10PlusInfo::input> &me) {
342 (void)mayBlock;
343 (void)me; // TODO: validate
344 return C2R::Ok();
345 }
346
347 static C2R Hdr10PlusInfoOutputSetter(bool mayBlock,
348 C2P<C2StreamHdr10PlusInfo::output> &me) {
349 (void)mayBlock;
350 (void)me; // TODO: validate
351 return C2R::Ok();
352 }
353
Harish Mahendrakar10c0c5d2022-05-30 20:35:16 -0700354 // unsafe getters
355 std::shared_ptr<C2StreamPixelFormatInfo::output> getPixelFormat_l() const { return mPixelFormat; }
356
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530357 static C2R HdrStaticInfoSetter(bool mayBlock, C2P<C2StreamHdrStaticInfo::output> &me) {
358 (void)mayBlock;
359 if (me.v.mastering.red.x > 1) {
360 me.set().mastering.red.x = 1;
361 }
362 if (me.v.mastering.red.y > 1) {
363 me.set().mastering.red.y = 1;
364 }
365 if (me.v.mastering.green.x > 1) {
366 me.set().mastering.green.x = 1;
367 }
368 if (me.v.mastering.green.y > 1) {
369 me.set().mastering.green.y = 1;
370 }
371 if (me.v.mastering.blue.x > 1) {
372 me.set().mastering.blue.x = 1;
373 }
374 if (me.v.mastering.blue.y > 1) {
375 me.set().mastering.blue.y = 1;
376 }
377 if (me.v.mastering.white.x > 1) {
378 me.set().mastering.white.x = 1;
379 }
380 if (me.v.mastering.white.y > 1) {
381 me.set().mastering.white.y = 1;
382 }
383 if (me.v.mastering.maxLuminance > 65535.0) {
384 me.set().mastering.maxLuminance = 65535.0;
385 }
386 if (me.v.mastering.minLuminance > 6.5535) {
387 me.set().mastering.minLuminance = 6.5535;
388 }
389 if (me.v.maxCll > 65535.0) {
390 me.set().maxCll = 65535.0;
391 }
392 if (me.v.maxFall > 65535.0) {
393 me.set().maxFall = 65535.0;
394 }
395 return C2R::Ok();
396 }
397
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700398 private:
399 std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
400 std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
401 std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize;
402 std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize;
403 std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
404 std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
405 std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530406 std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects;
407 std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700408 std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput;
409 std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput;
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530410 std::shared_ptr<C2StreamHdrStaticInfo::output> mHdrStaticInfo;
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700411};
412
413C2SoftGav1Dec::C2SoftGav1Dec(const char *name, c2_node_id_t id,
414 const std::shared_ptr<IntfImpl> &intfImpl)
415 : SimpleC2Component(
416 std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700417 mIntf(intfImpl),
418 mCodecCtx(nullptr) {
Ray Essick24754942022-04-16 09:50:35 -0700419 mTimeStart = mTimeEnd = systemTime();
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700420}
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700421
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700422C2SoftGav1Dec::~C2SoftGav1Dec() { onRelease(); }
423
424c2_status_t C2SoftGav1Dec::onInit() {
425 return initDecoder() ? C2_OK : C2_CORRUPTED;
426}
427
428c2_status_t C2SoftGav1Dec::onStop() {
429 mSignalledError = false;
430 mSignalledOutputEos = false;
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700431 return C2_OK;
432}
433
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700434void C2SoftGav1Dec::onReset() {
435 (void)onStop();
436 c2_status_t err = onFlush_sm();
437 if (err != C2_OK) {
438 ALOGW("Failed to flush the av1 decoder. Trying to hard reset.");
439 destroyDecoder();
440 if (!initDecoder()) {
441 ALOGE("Hard reset failed.");
442 }
443 }
444}
445
446void C2SoftGav1Dec::onRelease() { destroyDecoder(); }
447
448c2_status_t C2SoftGav1Dec::onFlush_sm() {
James Zernb7aee6e2020-06-26 13:49:53 -0700449 Libgav1StatusCode status = mCodecCtx->SignalEOS();
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700450 if (status != kLibgav1StatusOk) {
451 ALOGE("Failed to flush av1 decoder. status: %d.", status);
452 return C2_CORRUPTED;
453 }
454
455 // Dequeue frame (if any) that was enqueued previously.
456 const libgav1::DecoderBuffer *buffer;
457 status = mCodecCtx->DequeueFrame(&buffer);
James Zernb7aee6e2020-06-26 13:49:53 -0700458 if (status != kLibgav1StatusOk && status != kLibgav1StatusNothingToDequeue) {
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700459 ALOGE("Failed to dequeue frame after flushing the av1 decoder. status: %d",
460 status);
461 return C2_CORRUPTED;
462 }
463
464 mSignalledError = false;
465 mSignalledOutputEos = false;
466
467 return C2_OK;
468}
469
470static int GetCPUCoreCount() {
471 int cpuCoreCount = 1;
472#if defined(_SC_NPROCESSORS_ONLN)
473 cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
474#else
475 // _SC_NPROC_ONLN must be defined...
476 cpuCoreCount = sysconf(_SC_NPROC_ONLN);
477#endif
478 CHECK(cpuCoreCount >= 1);
479 ALOGV("Number of CPU cores: %d", cpuCoreCount);
480 return cpuCoreCount;
481}
482
483bool C2SoftGav1Dec::initDecoder() {
484 mSignalledError = false;
485 mSignalledOutputEos = false;
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700486 mHalPixelFormat = HAL_PIXEL_FORMAT_YV12;
Harish Mahendrakar10c0c5d2022-05-30 20:35:16 -0700487 {
488 IntfImpl::Lock lock = mIntf->lock();
489 mPixelFormatInfo = mIntf->getPixelFormat_l();
490 }
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700491 mCodecCtx.reset(new libgav1::Decoder());
492
493 if (mCodecCtx == nullptr) {
494 ALOGE("mCodecCtx is null");
495 return false;
496 }
497
498 libgav1::DecoderSettings settings = {};
499 settings.threads = GetCPUCoreCount();
500
Vignesh Venkatasubramanian61ba2cf2019-06-24 10:04:00 -0700501 ALOGV("Using libgav1 AV1 software decoder.");
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700502 Libgav1StatusCode status = mCodecCtx->Init(&settings);
503 if (status != kLibgav1StatusOk) {
504 ALOGE("av1 decoder failed to initialize. status: %d.", status);
505 return false;
506 }
507
508 return true;
509}
510
511void C2SoftGav1Dec::destroyDecoder() { mCodecCtx = nullptr; }
512
513void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
514 uint32_t flags = 0;
515 if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
516 flags |= C2FrameData::FLAG_END_OF_STREAM;
517 ALOGV("signalling eos");
518 }
519 work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
520 work->worklets.front()->output.buffers.clear();
521 work->worklets.front()->output.ordinal = work->input.ordinal;
522 work->workletsProcessed = 1u;
523}
524
525void C2SoftGav1Dec::finishWork(uint64_t index,
526 const std::unique_ptr<C2Work> &work,
527 const std::shared_ptr<C2GraphicBlock> &block) {
528 std::shared_ptr<C2Buffer> buffer =
529 createGraphicBuffer(block, C2Rect(mWidth, mHeight));
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530530 {
531 IntfImpl::Lock lock = mIntf->lock();
532 buffer->setInfo(mIntf->getColorAspects_l());
533 }
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700534 auto fillWork = [buffer, index](const std::unique_ptr<C2Work> &work) {
535 uint32_t flags = 0;
536 if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
537 (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
538 flags |= C2FrameData::FLAG_END_OF_STREAM;
539 ALOGV("signalling eos");
540 }
541 work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
542 work->worklets.front()->output.buffers.clear();
543 work->worklets.front()->output.buffers.push_back(buffer);
544 work->worklets.front()->output.ordinal = work->input.ordinal;
545 work->workletsProcessed = 1u;
546 };
547 if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
548 fillWork(work);
549 } else {
550 finish(index, fillWork);
551 }
552}
553
554void C2SoftGav1Dec::process(const std::unique_ptr<C2Work> &work,
555 const std::shared_ptr<C2BlockPool> &pool) {
556 work->result = C2_OK;
557 work->workletsProcessed = 0u;
558 work->worklets.front()->output.configUpdate.clear();
559 work->worklets.front()->output.flags = work->input.flags;
560 if (mSignalledError || mSignalledOutputEos) {
561 work->result = C2_BAD_VALUE;
562 return;
563 }
564
565 size_t inOffset = 0u;
566 size_t inSize = 0u;
567 C2ReadView rView = mDummyReadView;
568 if (!work->input.buffers.empty()) {
569 rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
570 inSize = rView.capacity();
571 if (inSize && rView.error()) {
572 ALOGE("read view map failed %d", rView.error());
573 work->result = C2_CORRUPTED;
574 return;
575 }
576 }
577
578 bool codecConfig =
579 ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0);
580 bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
581
582 ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x", inSize,
583 (int)work->input.ordinal.timestamp.peeku(),
584 (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
585
586 if (codecConfig) {
587 fillEmptyWork(work);
588 return;
589 }
590
591 int64_t frameIndex = work->input.ordinal.frameIndex.peekll();
592 if (inSize) {
593 uint8_t *bitstream = const_cast<uint8_t *>(rView.data() + inOffset);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700594
Ray Essick24754942022-04-16 09:50:35 -0700595 mTimeStart = systemTime();
596 nsecs_t delay = mTimeStart - mTimeEnd;
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700597
598 const Libgav1StatusCode status =
James Zernb7aee6e2020-06-26 13:49:53 -0700599 mCodecCtx->EnqueueFrame(bitstream, inSize, frameIndex,
600 /*buffer_private_data=*/nullptr);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700601
Ray Essick24754942022-04-16 09:50:35 -0700602 mTimeEnd = systemTime();
603 nsecs_t decodeTime = mTimeEnd - mTimeStart;
604 ALOGV("decodeTime=%4" PRId64 " delay=%4" PRId64 "\n", decodeTime, delay);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700605
606 if (status != kLibgav1StatusOk) {
607 ALOGE("av1 decoder failed to decode frame. status: %d.", status);
608 work->result = C2_CORRUPTED;
609 work->workletsProcessed = 1u;
610 mSignalledError = true;
611 return;
612 }
613
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700614 }
615
616 (void)outputBuffer(pool, work);
617
618 if (eos) {
619 drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
620 mSignalledOutputEos = true;
621 } else if (!inSize) {
622 fillEmptyWork(work);
623 }
624}
625
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530626void C2SoftGav1Dec::getHDRStaticParams(const libgav1::DecoderBuffer *buffer,
627 const std::unique_ptr<C2Work> &work) {
628 C2StreamHdrStaticMetadataInfo::output hdrStaticMetadataInfo{};
629 bool infoPresent = false;
630 if (buffer->has_hdr_mdcv) {
631 // hdr_mdcv.primary_chromaticity_* values are in 0.16 fixed-point format.
632 hdrStaticMetadataInfo.mastering.red.x = buffer->hdr_mdcv.primary_chromaticity_x[0] / 65536.0;
633 hdrStaticMetadataInfo.mastering.red.y = buffer->hdr_mdcv.primary_chromaticity_y[0] / 65536.0;
634
635 hdrStaticMetadataInfo.mastering.green.x = buffer->hdr_mdcv.primary_chromaticity_x[1] / 65536.0;
636 hdrStaticMetadataInfo.mastering.green.y = buffer->hdr_mdcv.primary_chromaticity_y[1] / 65536.0;
637
638 hdrStaticMetadataInfo.mastering.blue.x = buffer->hdr_mdcv.primary_chromaticity_x[2] / 65536.0;
639 hdrStaticMetadataInfo.mastering.blue.y = buffer->hdr_mdcv.primary_chromaticity_y[2] / 65536.0;
640
641 // hdr_mdcv.white_point_chromaticity_* values are in 0.16 fixed-point format.
642 hdrStaticMetadataInfo.mastering.white.x = buffer->hdr_mdcv.white_point_chromaticity_x / 65536.0;
643 hdrStaticMetadataInfo.mastering.white.y = buffer->hdr_mdcv.white_point_chromaticity_y / 65536.0;
644
645 // hdr_mdcv.luminance_max is in 24.8 fixed-point format.
646 hdrStaticMetadataInfo.mastering.maxLuminance = buffer->hdr_mdcv.luminance_max / 256.0;
647 // hdr_mdcv.luminance_min is in 18.14 format.
648 hdrStaticMetadataInfo.mastering.minLuminance = buffer->hdr_mdcv.luminance_min / 16384.0;
649 infoPresent = true;
650 }
651
652 if (buffer->has_hdr_cll) {
653 hdrStaticMetadataInfo.maxCll = buffer->hdr_cll.max_cll;
654 hdrStaticMetadataInfo.maxFall = buffer->hdr_cll.max_fall;
655 infoPresent = true;
656 }
657 // config if static info has changed
658 if (infoPresent && !(hdrStaticMetadataInfo == mHdrStaticMetadataInfo)) {
659 mHdrStaticMetadataInfo = hdrStaticMetadataInfo;
660 work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(mHdrStaticMetadataInfo));
661 }
662}
663
664void C2SoftGav1Dec::getHDR10PlusInfoData(const libgav1::DecoderBuffer *buffer,
665 const std::unique_ptr<C2Work> &work) {
666 if (buffer->has_itut_t35) {
667 std::vector<uint8_t> payload;
668 size_t payloadSize = buffer->itut_t35.payload_size;
669 if (payloadSize > 0) {
670 payload.push_back(buffer->itut_t35.country_code);
671 if (buffer->itut_t35.country_code == 0xFF) {
672 payload.push_back(buffer->itut_t35.country_code_extension_byte);
673 }
674 payload.insert(payload.end(), buffer->itut_t35.payload_bytes,
675 buffer->itut_t35.payload_bytes + buffer->itut_t35.payload_size);
676 }
677
678 std::unique_ptr<C2StreamHdr10PlusInfo::output> hdr10PlusInfo =
679 C2StreamHdr10PlusInfo::output::AllocUnique(payload.size());
680 if (!hdr10PlusInfo) {
681 ALOGE("Hdr10PlusInfo allocation failed");
682 mSignalledError = true;
683 work->result = C2_NO_MEMORY;
684 return;
685 }
686 memcpy(hdr10PlusInfo->m.value, payload.data(), payload.size());
687
688 // config if hdr10Plus info has changed
689 if (nullptr == mHdr10PlusInfo || !(*hdr10PlusInfo == *mHdr10PlusInfo)) {
690 mHdr10PlusInfo = std::move(hdr10PlusInfo);
691 work->worklets.front()->output.configUpdate.push_back(std::move(mHdr10PlusInfo));
692 }
693 }
694}
695
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530696void C2SoftGav1Dec::getVuiParams(const libgav1::DecoderBuffer *buffer) {
697 VuiColorAspects vuiColorAspects;
698 vuiColorAspects.primaries = buffer->color_primary;
699 vuiColorAspects.transfer = buffer->transfer_characteristics;
700 vuiColorAspects.coeffs = buffer->matrix_coefficients;
701 vuiColorAspects.fullRange = buffer->color_range;
702
703 // convert vui aspects to C2 values if changed
704 if (!(vuiColorAspects == mBitstreamColorAspects)) {
705 mBitstreamColorAspects = vuiColorAspects;
706 ColorAspects sfAspects;
707 C2StreamColorAspectsInfo::input codedAspects = { 0u };
708 ColorUtils::convertIsoColorAspectsToCodecAspects(
709 vuiColorAspects.primaries, vuiColorAspects.transfer, vuiColorAspects.coeffs,
710 vuiColorAspects.fullRange, sfAspects);
711 if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) {
712 codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED;
713 }
714 if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) {
715 codedAspects.range = C2Color::RANGE_UNSPECIFIED;
716 }
717 if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) {
718 codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED;
719 }
720 if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) {
721 codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED;
722 }
723 std::vector<std::unique_ptr<C2SettingResult>> failures;
724 mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures);
725 }
726}
727
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700728bool C2SoftGav1Dec::outputBuffer(const std::shared_ptr<C2BlockPool> &pool,
729 const std::unique_ptr<C2Work> &work) {
730 if (!(work && pool)) return false;
731
732 const libgav1::DecoderBuffer *buffer;
733 const Libgav1StatusCode status = mCodecCtx->DequeueFrame(&buffer);
734
James Zernb7aee6e2020-06-26 13:49:53 -0700735 if (status != kLibgav1StatusOk && status != kLibgav1StatusNothingToDequeue) {
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700736 ALOGE("av1 decoder DequeueFrame failed. status: %d.", status);
737 return false;
738 }
739
James Zernb7aee6e2020-06-26 13:49:53 -0700740 // |buffer| can be NULL if status was equal to kLibgav1StatusOk or
741 // kLibgav1StatusNothingToDequeue. This is not an error. This could mean one
742 // of two things:
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700743 // - The EnqueueFrame() call was either a flush (called with nullptr).
744 // - The enqueued frame did not have any displayable frames.
745 if (!buffer) {
746 return false;
747 }
748
749 const int width = buffer->displayed_width[0];
750 const int height = buffer->displayed_height[0];
751 if (width != mWidth || height != mHeight) {
752 mWidth = width;
753 mHeight = height;
754
755 C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
756 std::vector<std::unique_ptr<C2SettingResult>> failures;
757 c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
758 if (err == C2_OK) {
759 work->worklets.front()->output.configUpdate.push_back(
760 C2Param::Copy(size));
761 } else {
762 ALOGE("Config update size failed");
763 mSignalledError = true;
764 work->result = C2_CORRUPTED;
765 work->workletsProcessed = 1u;
766 return false;
767 }
768 }
769
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530770 getVuiParams(buffer);
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530771 getHDRStaticParams(buffer, work);
772 getHDR10PlusInfoData(buffer, work);
773
James Zern4d25d652021-06-22 18:10:13 -0700774 if (!(buffer->image_format == libgav1::kImageFormatYuv420 ||
775 buffer->image_format == libgav1::kImageFormatMonochrome400)) {
776 ALOGE("image_format %d not supported", buffer->image_format);
777 mSignalledError = true;
778 work->workletsProcessed = 1u;
779 work->result = C2_CORRUPTED;
780 return false;
781 }
Vignesh Venkatasubramanianca7d1ab2021-02-04 12:39:06 -0800782 const bool isMonochrome =
783 buffer->image_format == libgav1::kImageFormatMonochrome400;
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700784
785 std::shared_ptr<C2GraphicBlock> block;
786 uint32_t format = HAL_PIXEL_FORMAT_YV12;
Lajos Molnar45109a32022-06-03 09:41:48 -0700787 std::shared_ptr<C2StreamColorAspectsInfo::output> codedColorAspects;
Harish Mahendrakar10c0c5d2022-05-30 20:35:16 -0700788 if (buffer->bitdepth == 10 && mPixelFormatInfo->value != HAL_PIXEL_FORMAT_YCBCR_420_888) {
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700789 IntfImpl::Lock lock = mIntf->lock();
Lajos Molnar45109a32022-06-03 09:41:48 -0700790 codedColorAspects = mIntf->getColorAspects_l();
Harish Mahendrakar749a74c2022-01-27 16:47:09 -0800791 bool allowRGBA1010102 = false;
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530792 if (codedColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
793 codedColorAspects->matrix == C2Color::MATRIX_BT2020 &&
794 codedColorAspects->transfer == C2Color::TRANSFER_ST2084) {
Harish Mahendrakar749a74c2022-01-27 16:47:09 -0800795 allowRGBA1010102 = true;
796 }
797 format = getHalPixelFormatForBitDepth10(allowRGBA1010102);
798 if ((format == HAL_PIXEL_FORMAT_RGBA_1010102) &&
799 (buffer->image_format != libgav1::kImageFormatYuv420)) {
Vignesh Venkatasubramanianca7d1ab2021-02-04 12:39:06 -0800800 ALOGE("Only YUV420 output is supported when targeting RGBA_1010102");
Harish Mahendrakar749a74c2022-01-27 16:47:09 -0800801 mSignalledError = true;
802 work->result = C2_OMITTED;
803 work->workletsProcessed = 1u;
804 return false;
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700805 }
806 }
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700807
808 if (mHalPixelFormat != format) {
809 C2StreamPixelFormatInfo::output pixelFormat(0u, format);
810 std::vector<std::unique_ptr<C2SettingResult>> failures;
811 c2_status_t err = mIntf->config({&pixelFormat }, C2_MAY_BLOCK, &failures);
812 if (err == C2_OK) {
813 work->worklets.front()->output.configUpdate.push_back(
814 C2Param::Copy(pixelFormat));
815 } else {
816 ALOGE("Config update pixelFormat failed");
817 mSignalledError = true;
818 work->workletsProcessed = 1u;
819 work->result = C2_CORRUPTED;
820 return UNKNOWN_ERROR;
821 }
822 mHalPixelFormat = format;
823 }
824
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700825 C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
826
Vignesh Venkatasubramanianc4d385f2022-02-22 10:49:46 -0800827 // We always create a graphic block that is width aligned to 16 and height
828 // aligned to 2. We set the correct "crop" value of the image in the call to
829 // createGraphicBuffer() by setting the correct image dimensions.
830 c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16),
831 align(mHeight, 2), format, usage,
832 &block);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700833
834 if (err != C2_OK) {
835 ALOGE("fetchGraphicBlock for Output failed with status %d", err);
836 work->result = err;
837 return false;
838 }
839
840 C2GraphicView wView = block->map().get();
841
842 if (wView.error()) {
843 ALOGE("graphic view map failed %d", wView.error());
844 work->result = C2_CORRUPTED;
845 return false;
846 }
847
848 ALOGV("provided (%dx%d) required (%dx%d), out frameindex %d", block->width(),
849 block->height(), mWidth, mHeight, (int)buffer->user_private_data);
850
ming.zhouac19c3d2019-10-11 11:14:07 +0800851 uint8_t *dstY = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_Y]);
852 uint8_t *dstU = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_U]);
853 uint8_t *dstV = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_V]);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700854 size_t srcYStride = buffer->stride[0];
855 size_t srcUStride = buffer->stride[1];
856 size_t srcVStride = buffer->stride[2];
857
ming.zhouac19c3d2019-10-11 11:14:07 +0800858 C2PlanarLayout layout = wView.layout();
859 size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
860 size_t dstUVStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
861
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700862 if (buffer->bitdepth == 10) {
863 const uint16_t *srcY = (const uint16_t *)buffer->plane[0];
864 const uint16_t *srcU = (const uint16_t *)buffer->plane[1];
865 const uint16_t *srcV = (const uint16_t *)buffer->plane[2];
866
867 if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
Lajos Molnar45109a32022-06-03 09:41:48 -0700868 convertYUV420Planar16ToY410OrRGBA1010102(
869 (uint32_t *)dstY, srcY, srcU, srcV, srcYStride / 2,
870 srcUStride / 2, srcVStride / 2,
871 dstYStride / sizeof(uint32_t), mWidth, mHeight,
872 std::static_pointer_cast<const C2ColorAspectsStruct>(codedColorAspects));
Harish Mahendrakar1b1aef22021-12-30 19:12:51 -0800873 } else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
874 convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
875 srcYStride / 2, srcUStride / 2, srcVStride / 2, dstYStride / 2,
876 dstUVStride / 2, mWidth, mHeight, isMonochrome);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700877 } else {
Harish Mahendrakar1b1aef22021-12-30 19:12:51 -0800878 convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
879 srcUStride / 2, srcVStride / 2, dstYStride, dstUVStride, mWidth,
880 mHeight, isMonochrome);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700881 }
882 } else {
883 const uint8_t *srcY = (const uint8_t *)buffer->plane[0];
884 const uint8_t *srcU = (const uint8_t *)buffer->plane[1];
885 const uint8_t *srcV = (const uint8_t *)buffer->plane[2];
Harish Mahendrakar1b1aef22021-12-30 19:12:51 -0800886 convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
887 srcVStride, dstYStride, dstUVStride, mWidth, mHeight, isMonochrome);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700888 }
889 finishWork(buffer->user_private_data, work, std::move(block));
890 block = nullptr;
891 return true;
892}
893
894c2_status_t C2SoftGav1Dec::drainInternal(
895 uint32_t drainMode, const std::shared_ptr<C2BlockPool> &pool,
896 const std::unique_ptr<C2Work> &work) {
897 if (drainMode == NO_DRAIN) {
898 ALOGW("drain with NO_DRAIN: no-op");
899 return C2_OK;
900 }
901 if (drainMode == DRAIN_CHAIN) {
902 ALOGW("DRAIN_CHAIN not supported");
903 return C2_OMITTED;
904 }
905
James Zernb7aee6e2020-06-26 13:49:53 -0700906 const Libgav1StatusCode status = mCodecCtx->SignalEOS();
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700907 if (status != kLibgav1StatusOk) {
908 ALOGE("Failed to flush av1 decoder. status: %d.", status);
909 return C2_CORRUPTED;
910 }
911
912 while (outputBuffer(pool, work)) {
913 }
914
915 if (drainMode == DRAIN_COMPONENT_WITH_EOS && work &&
916 work->workletsProcessed == 0u) {
917 fillEmptyWork(work);
918 }
919
920 return C2_OK;
921}
922
923c2_status_t C2SoftGav1Dec::drain(uint32_t drainMode,
924 const std::shared_ptr<C2BlockPool> &pool) {
925 return drainInternal(drainMode, pool, nullptr);
926}
927
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700928class C2SoftGav1Factory : public C2ComponentFactory {
929 public:
930 C2SoftGav1Factory()
931 : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
932 GetCodec2PlatformComponentStore()->getParamReflector())) {}
933
934 virtual c2_status_t createComponent(
935 c2_node_id_t id, std::shared_ptr<C2Component> *const component,
936 std::function<void(C2Component *)> deleter) override {
937 *component = std::shared_ptr<C2Component>(
938 new C2SoftGav1Dec(COMPONENT_NAME, id,
939 std::make_shared<C2SoftGav1Dec::IntfImpl>(mHelper)),
940 deleter);
941 return C2_OK;
942 }
943
944 virtual c2_status_t createInterface(
945 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *const interface,
946 std::function<void(C2ComponentInterface *)> deleter) override {
947 *interface = std::shared_ptr<C2ComponentInterface>(
948 new SimpleInterface<C2SoftGav1Dec::IntfImpl>(
949 COMPONENT_NAME, id,
950 std::make_shared<C2SoftGav1Dec::IntfImpl>(mHelper)),
951 deleter);
952 return C2_OK;
953 }
954
955 virtual ~C2SoftGav1Factory() override = default;
956
957 private:
958 std::shared_ptr<C2ReflectorHelper> mHelper;
959};
960
961} // namespace android
962
Cindy Zhouf6c0c3c2020-12-02 10:53:40 -0800963__attribute__((cfi_canonical_jump_table))
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700964extern "C" ::C2ComponentFactory *CreateCodec2Factory() {
965 ALOGV("in %s", __func__);
966 return new ::android::C2SoftGav1Factory();
967}
968
Cindy Zhouf6c0c3c2020-12-02 10:53:40 -0800969__attribute__((cfi_canonical_jump_table))
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700970extern "C" void DestroyCodec2Factory(::C2ComponentFactory *factory) {
971 ALOGV("in %s", __func__);
972 delete factory;
973}