blob: 8aed623786b52d8dcc745f968679447805810792 [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>
Vignesh Venkatasubramanian406ed312022-04-21 10:32:55 -070027#include <libyuv.h>
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -070028#include <log/log.h>
29#include <media/stagefright/foundation/AUtils.h>
30#include <media/stagefright/foundation/MediaDefs.h>
31
32namespace android {
33
Ray Essickc2cc4372019-08-21 14:02:28 -070034// codecname set and passed in as a compile flag from Android.bp
35constexpr char COMPONENT_NAME[] = CODECNAME;
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -070036
Ray Essick1af2cc52022-01-25 15:59:23 -080037constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
38
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -070039class C2SoftGav1Dec::IntfImpl : public SimpleInterface<void>::BaseParams {
40 public:
41 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
42 : SimpleInterface<void>::BaseParams(
43 helper, COMPONENT_NAME, C2Component::KIND_DECODER,
44 C2Component::DOMAIN_VIDEO, MEDIA_MIMETYPE_VIDEO_AV1) {
45 noPrivateBuffers(); // TODO: account for our buffers here.
46 noInputReferences();
47 noOutputReferences();
48 noInputLatency();
49 noTimeStretch();
50
51 addParameter(DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
52 .withConstValue(new C2ComponentAttributesSetting(
53 C2Component::ATTRIB_IS_TEMPORAL))
54 .build());
55
56 addParameter(
57 DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
58 .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
59 .withFields({
Vignesh Venkatasubramanianc4d385f2022-02-22 10:49:46 -080060 C2F(mSize, width).inRange(2, 4096),
61 C2F(mSize, height).inRange(2, 4096),
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -070062 })
63 .withSetter(SizeSetter)
64 .build());
65
66 addParameter(DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
67 .withDefault(new C2StreamProfileLevelInfo::input(
68 0u, C2Config::PROFILE_AV1_0, C2Config::LEVEL_AV1_2_1))
69 .withFields({C2F(mProfileLevel, profile)
70 .oneOf({C2Config::PROFILE_AV1_0,
71 C2Config::PROFILE_AV1_1}),
72 C2F(mProfileLevel, level)
73 .oneOf({
Harish Mahendrakar1ad8c3b2021-06-04 15:42:31 -070074 C2Config::LEVEL_AV1_2, C2Config::LEVEL_AV1_2_1,
75 C2Config::LEVEL_AV1_2_2, C2Config::LEVEL_AV1_2_3,
76 C2Config::LEVEL_AV1_3, C2Config::LEVEL_AV1_3_1,
77 C2Config::LEVEL_AV1_3_2, C2Config::LEVEL_AV1_3_3,
78 C2Config::LEVEL_AV1_4, C2Config::LEVEL_AV1_4_1,
79 C2Config::LEVEL_AV1_4_2, C2Config::LEVEL_AV1_4_3,
80 C2Config::LEVEL_AV1_5, C2Config::LEVEL_AV1_5_1,
81 C2Config::LEVEL_AV1_5_2, C2Config::LEVEL_AV1_5_3,
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -070082 })})
83 .withSetter(ProfileLevelSetter, mSize)
84 .build());
85
86 mHdr10PlusInfoInput = C2StreamHdr10PlusInfo::input::AllocShared(0);
87 addParameter(
88 DefineParam(mHdr10PlusInfoInput, C2_PARAMKEY_INPUT_HDR10_PLUS_INFO)
89 .withDefault(mHdr10PlusInfoInput)
90 .withFields({
91 C2F(mHdr10PlusInfoInput, m.value).any(),
92 })
93 .withSetter(Hdr10PlusInfoInputSetter)
94 .build());
95
96 mHdr10PlusInfoOutput = C2StreamHdr10PlusInfo::output::AllocShared(0);
97 addParameter(
98 DefineParam(mHdr10PlusInfoOutput, C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO)
99 .withDefault(mHdr10PlusInfoOutput)
100 .withFields({
101 C2F(mHdr10PlusInfoOutput, m.value).any(),
102 })
103 .withSetter(Hdr10PlusInfoOutputSetter)
104 .build());
105
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530106 // default static info
107 C2HdrStaticMetadataStruct defaultStaticInfo{};
108 helper->addStructDescriptors<C2MasteringDisplayColorVolumeStruct, C2ColorXyStruct>();
109 addParameter(
110 DefineParam(mHdrStaticInfo, C2_PARAMKEY_HDR_STATIC_INFO)
111 .withDefault(new C2StreamHdrStaticInfo::output(0u, defaultStaticInfo))
112 .withFields({
113 C2F(mHdrStaticInfo, mastering.red.x).inRange(0, 1),
114 C2F(mHdrStaticInfo, mastering.red.y).inRange(0, 1),
115 C2F(mHdrStaticInfo, mastering.green.x).inRange(0, 1),
116 C2F(mHdrStaticInfo, mastering.green.y).inRange(0, 1),
117 C2F(mHdrStaticInfo, mastering.blue.x).inRange(0, 1),
118 C2F(mHdrStaticInfo, mastering.blue.y).inRange(0, 1),
119 C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
120 C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
121 C2F(mHdrStaticInfo, mastering.maxLuminance).inRange(0, 65535),
122 C2F(mHdrStaticInfo, mastering.minLuminance).inRange(0, 6.5535),
123 C2F(mHdrStaticInfo, maxCll).inRange(0, 0XFFFF),
124 C2F(mHdrStaticInfo, maxFall).inRange(0, 0XFFFF)
125 })
126 .withSetter(HdrStaticInfoSetter)
127 .build());
128
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700129 addParameter(
130 DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
131 .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240))
132 .withFields({
133 C2F(mSize, width).inRange(2, 2048, 2),
134 C2F(mSize, height).inRange(2, 2048, 2),
135 })
136 .withSetter(MaxPictureSizeSetter, mSize)
137 .build());
138
139 addParameter(DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
Ray Essick1af2cc52022-01-25 15:59:23 -0800140 .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700141 .withFields({
142 C2F(mMaxInputSize, value).any(),
143 })
144 .calculatedAs(MaxInputSizeSetter, mMaxSize)
145 .build());
146
147 C2ChromaOffsetStruct locations[1] = {C2ChromaOffsetStruct::ITU_YUV_420_0()};
148 std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
149 C2StreamColorInfo::output::AllocShared(1u, 0u, 8u /* bitDepth */,
150 C2Color::YUV_420);
151 memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
152
153 defaultColorInfo = C2StreamColorInfo::output::AllocShared(
154 {C2ChromaOffsetStruct::ITU_YUV_420_0()}, 0u, 8u /* bitDepth */,
155 C2Color::YUV_420);
156 helper->addStructDescriptors<C2ChromaOffsetStruct>();
157
158 addParameter(DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
159 .withConstValue(defaultColorInfo)
160 .build());
161
162 addParameter(
163 DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
164 .withDefault(new C2StreamColorAspectsTuning::output(
165 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
166 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
167 .withFields(
168 {C2F(mDefaultColorAspects, range)
169 .inRange(C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
170 C2F(mDefaultColorAspects, primaries)
171 .inRange(C2Color::PRIMARIES_UNSPECIFIED,
172 C2Color::PRIMARIES_OTHER),
173 C2F(mDefaultColorAspects, transfer)
174 .inRange(C2Color::TRANSFER_UNSPECIFIED,
175 C2Color::TRANSFER_OTHER),
176 C2F(mDefaultColorAspects, matrix)
177 .inRange(C2Color::MATRIX_UNSPECIFIED,
178 C2Color::MATRIX_OTHER)})
179 .withSetter(DefaultColorAspectsSetter)
180 .build());
181
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530182 addParameter(
183 DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
184 .withDefault(new C2StreamColorAspectsInfo::input(
185 0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
186 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
187 .withFields({
188 C2F(mCodedColorAspects, range).inRange(
189 C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
190 C2F(mCodedColorAspects, primaries).inRange(
191 C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
192 C2F(mCodedColorAspects, transfer).inRange(
193 C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
194 C2F(mCodedColorAspects, matrix).inRange(
195 C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
196 })
197 .withSetter(CodedColorAspectsSetter)
198 .build());
199
200 addParameter(
201 DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
202 .withDefault(new C2StreamColorAspectsInfo::output(
203 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
204 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
205 .withFields({
206 C2F(mColorAspects, range).inRange(
207 C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
208 C2F(mColorAspects, primaries).inRange(
209 C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
210 C2F(mColorAspects, transfer).inRange(
211 C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
212 C2F(mColorAspects, matrix).inRange(
213 C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
214 })
215 .withSetter(ColorAspectsSetter, mDefaultColorAspects, mCodedColorAspects)
216 .build());
217
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700218 std::vector<uint32_t> pixelFormats = {HAL_PIXEL_FORMAT_YCBCR_420_888};
Harish Mahendrakarf5dec502022-04-13 15:53:55 -0700219 if (isHalPixelFormatSupported((AHardwareBuffer_Format)HAL_PIXEL_FORMAT_YCBCR_P010)) {
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700220 pixelFormats.push_back(HAL_PIXEL_FORMAT_YCBCR_P010);
221 }
Harish Mahendrakar10c0c5d2022-05-30 20:35:16 -0700222 // If color format surface isn't added to supported formats, there is no way to know
223 // when the color-format is configured to surface. This is necessary to be able to
224 // choose 10-bit format while decoding 10-bit clips in surface mode.
225 pixelFormats.push_back(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
226
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700227 // TODO: support more formats?
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700228 addParameter(
229 DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
230 .withDefault(new C2StreamPixelFormatInfo::output(
231 0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
232 .withFields({C2F(mPixelFormat, value).oneOf(pixelFormats)})
233 .withSetter((Setter<decltype(*mPixelFormat)>::StrictValueWithNoDeps))
234 .build());
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700235 }
236
237 static C2R SizeSetter(bool mayBlock,
238 const C2P<C2StreamPictureSizeInfo::output> &oldMe,
239 C2P<C2StreamPictureSizeInfo::output> &me) {
240 (void)mayBlock;
241 C2R res = C2R::Ok();
242 if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
243 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
244 me.set().width = oldMe.v.width;
245 }
246 if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
247 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
248 me.set().height = oldMe.v.height;
249 }
250 return res;
251 }
252
253 static C2R MaxPictureSizeSetter(
254 bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output> &me,
255 const C2P<C2StreamPictureSizeInfo::output> &size) {
256 (void)mayBlock;
257 // TODO: get max width/height from the size's field helpers vs.
258 // hardcoding
259 me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4096u);
260 me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4096u);
261 return C2R::Ok();
262 }
263
264 static C2R MaxInputSizeSetter(
265 bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me,
266 const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
267 (void)mayBlock;
Ray Essick1af2cc52022-01-25 15:59:23 -0800268 // assume compression ratio of 2, but enforce a floor
269 me.set().value = c2_max((((maxSize.v.width + 63) / 64)
270 * ((maxSize.v.height + 63) / 64) * 3072), kMinInputBufferSize);
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700271 return C2R::Ok();
272 }
273
274 static C2R DefaultColorAspectsSetter(
275 bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) {
276 (void)mayBlock;
277 if (me.v.range > C2Color::RANGE_OTHER) {
278 me.set().range = C2Color::RANGE_OTHER;
279 }
280 if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
281 me.set().primaries = C2Color::PRIMARIES_OTHER;
282 }
283 if (me.v.transfer > C2Color::TRANSFER_OTHER) {
284 me.set().transfer = C2Color::TRANSFER_OTHER;
285 }
286 if (me.v.matrix > C2Color::MATRIX_OTHER) {
287 me.set().matrix = C2Color::MATRIX_OTHER;
288 }
289 return C2R::Ok();
290 }
291
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530292 static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) {
293 (void)mayBlock;
294 if (me.v.range > C2Color::RANGE_OTHER) {
295 me.set().range = C2Color::RANGE_OTHER;
296 }
297 if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
298 me.set().primaries = C2Color::PRIMARIES_OTHER;
299 }
300 if (me.v.transfer > C2Color::TRANSFER_OTHER) {
301 me.set().transfer = C2Color::TRANSFER_OTHER;
302 }
303 if (me.v.matrix > C2Color::MATRIX_OTHER) {
304 me.set().matrix = C2Color::MATRIX_OTHER;
305 }
306 return C2R::Ok();
307 }
308
309 static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
310 const C2P<C2StreamColorAspectsTuning::output> &def,
311 const C2P<C2StreamColorAspectsInfo::input> &coded) {
312 (void)mayBlock;
313 // take default values for all unspecified fields, and coded values for specified ones
314 me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range;
315 me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED
316 ? def.v.primaries : coded.v.primaries;
317 me.set().transfer = coded.v.transfer == TRANSFER_UNSPECIFIED
318 ? def.v.transfer : coded.v.transfer;
319 me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix : coded.v.matrix;
320 return C2R::Ok();
321 }
322
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700323 static C2R ProfileLevelSetter(
324 bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
325 const C2P<C2StreamPictureSizeInfo::output> &size) {
326 (void)mayBlock;
327 (void)size;
328 (void)me; // TODO: validate
329 return C2R::Ok();
330 }
331
332 std::shared_ptr<C2StreamColorAspectsTuning::output>
333 getDefaultColorAspects_l() {
334 return mDefaultColorAspects;
335 }
336
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530337 std::shared_ptr<C2StreamColorAspectsInfo::output> getColorAspects_l() {
338 return mColorAspects;
339 }
340
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700341 static C2R Hdr10PlusInfoInputSetter(bool mayBlock,
342 C2P<C2StreamHdr10PlusInfo::input> &me) {
343 (void)mayBlock;
344 (void)me; // TODO: validate
345 return C2R::Ok();
346 }
347
348 static C2R Hdr10PlusInfoOutputSetter(bool mayBlock,
349 C2P<C2StreamHdr10PlusInfo::output> &me) {
350 (void)mayBlock;
351 (void)me; // TODO: validate
352 return C2R::Ok();
353 }
354
Harish Mahendrakar10c0c5d2022-05-30 20:35:16 -0700355 // unsafe getters
356 std::shared_ptr<C2StreamPixelFormatInfo::output> getPixelFormat_l() const { return mPixelFormat; }
357
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530358 static C2R HdrStaticInfoSetter(bool mayBlock, C2P<C2StreamHdrStaticInfo::output> &me) {
359 (void)mayBlock;
360 if (me.v.mastering.red.x > 1) {
361 me.set().mastering.red.x = 1;
362 }
363 if (me.v.mastering.red.y > 1) {
364 me.set().mastering.red.y = 1;
365 }
366 if (me.v.mastering.green.x > 1) {
367 me.set().mastering.green.x = 1;
368 }
369 if (me.v.mastering.green.y > 1) {
370 me.set().mastering.green.y = 1;
371 }
372 if (me.v.mastering.blue.x > 1) {
373 me.set().mastering.blue.x = 1;
374 }
375 if (me.v.mastering.blue.y > 1) {
376 me.set().mastering.blue.y = 1;
377 }
378 if (me.v.mastering.white.x > 1) {
379 me.set().mastering.white.x = 1;
380 }
381 if (me.v.mastering.white.y > 1) {
382 me.set().mastering.white.y = 1;
383 }
384 if (me.v.mastering.maxLuminance > 65535.0) {
385 me.set().mastering.maxLuminance = 65535.0;
386 }
387 if (me.v.mastering.minLuminance > 6.5535) {
388 me.set().mastering.minLuminance = 6.5535;
389 }
390 if (me.v.maxCll > 65535.0) {
391 me.set().maxCll = 65535.0;
392 }
393 if (me.v.maxFall > 65535.0) {
394 me.set().maxFall = 65535.0;
395 }
396 return C2R::Ok();
397 }
398
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700399 private:
400 std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
401 std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
402 std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize;
403 std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize;
404 std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
405 std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
406 std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530407 std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects;
408 std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700409 std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput;
410 std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput;
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530411 std::shared_ptr<C2StreamHdrStaticInfo::output> mHdrStaticInfo;
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700412};
413
414C2SoftGav1Dec::C2SoftGav1Dec(const char *name, c2_node_id_t id,
415 const std::shared_ptr<IntfImpl> &intfImpl)
416 : SimpleC2Component(
417 std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700418 mIntf(intfImpl),
419 mCodecCtx(nullptr) {
Ray Essick24754942022-04-16 09:50:35 -0700420 mTimeStart = mTimeEnd = systemTime();
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700421}
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700422
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700423C2SoftGav1Dec::~C2SoftGav1Dec() { onRelease(); }
424
425c2_status_t C2SoftGav1Dec::onInit() {
426 return initDecoder() ? C2_OK : C2_CORRUPTED;
427}
428
429c2_status_t C2SoftGav1Dec::onStop() {
430 mSignalledError = false;
431 mSignalledOutputEos = false;
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700432 return C2_OK;
433}
434
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700435void C2SoftGav1Dec::onReset() {
436 (void)onStop();
437 c2_status_t err = onFlush_sm();
438 if (err != C2_OK) {
439 ALOGW("Failed to flush the av1 decoder. Trying to hard reset.");
440 destroyDecoder();
441 if (!initDecoder()) {
442 ALOGE("Hard reset failed.");
443 }
444 }
445}
446
447void C2SoftGav1Dec::onRelease() { destroyDecoder(); }
448
449c2_status_t C2SoftGav1Dec::onFlush_sm() {
James Zernb7aee6e2020-06-26 13:49:53 -0700450 Libgav1StatusCode status = mCodecCtx->SignalEOS();
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700451 if (status != kLibgav1StatusOk) {
452 ALOGE("Failed to flush av1 decoder. status: %d.", status);
453 return C2_CORRUPTED;
454 }
455
456 // Dequeue frame (if any) that was enqueued previously.
457 const libgav1::DecoderBuffer *buffer;
458 status = mCodecCtx->DequeueFrame(&buffer);
James Zernb7aee6e2020-06-26 13:49:53 -0700459 if (status != kLibgav1StatusOk && status != kLibgav1StatusNothingToDequeue) {
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700460 ALOGE("Failed to dequeue frame after flushing the av1 decoder. status: %d",
461 status);
462 return C2_CORRUPTED;
463 }
464
465 mSignalledError = false;
466 mSignalledOutputEos = false;
467
468 return C2_OK;
469}
470
471static int GetCPUCoreCount() {
472 int cpuCoreCount = 1;
473#if defined(_SC_NPROCESSORS_ONLN)
474 cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
475#else
476 // _SC_NPROC_ONLN must be defined...
477 cpuCoreCount = sysconf(_SC_NPROC_ONLN);
478#endif
479 CHECK(cpuCoreCount >= 1);
480 ALOGV("Number of CPU cores: %d", cpuCoreCount);
481 return cpuCoreCount;
482}
483
484bool C2SoftGav1Dec::initDecoder() {
485 mSignalledError = false;
486 mSignalledOutputEos = false;
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700487 mHalPixelFormat = HAL_PIXEL_FORMAT_YV12;
Harish Mahendrakar10c0c5d2022-05-30 20:35:16 -0700488 {
489 IntfImpl::Lock lock = mIntf->lock();
490 mPixelFormatInfo = mIntf->getPixelFormat_l();
491 }
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700492 mCodecCtx.reset(new libgav1::Decoder());
493
494 if (mCodecCtx == nullptr) {
495 ALOGE("mCodecCtx is null");
496 return false;
497 }
498
499 libgav1::DecoderSettings settings = {};
500 settings.threads = GetCPUCoreCount();
501
Vignesh Venkatasubramanian61ba2cf2019-06-24 10:04:00 -0700502 ALOGV("Using libgav1 AV1 software decoder.");
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700503 Libgav1StatusCode status = mCodecCtx->Init(&settings);
504 if (status != kLibgav1StatusOk) {
505 ALOGE("av1 decoder failed to initialize. status: %d.", status);
506 return false;
507 }
508
509 return true;
510}
511
512void C2SoftGav1Dec::destroyDecoder() { mCodecCtx = nullptr; }
513
514void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
515 uint32_t flags = 0;
516 if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
517 flags |= C2FrameData::FLAG_END_OF_STREAM;
518 ALOGV("signalling eos");
519 }
520 work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
521 work->worklets.front()->output.buffers.clear();
522 work->worklets.front()->output.ordinal = work->input.ordinal;
523 work->workletsProcessed = 1u;
524}
525
526void C2SoftGav1Dec::finishWork(uint64_t index,
527 const std::unique_ptr<C2Work> &work,
528 const std::shared_ptr<C2GraphicBlock> &block) {
529 std::shared_ptr<C2Buffer> buffer =
530 createGraphicBuffer(block, C2Rect(mWidth, mHeight));
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530531 {
532 IntfImpl::Lock lock = mIntf->lock();
533 buffer->setInfo(mIntf->getColorAspects_l());
534 }
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700535 auto fillWork = [buffer, index](const std::unique_ptr<C2Work> &work) {
536 uint32_t flags = 0;
537 if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
538 (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
539 flags |= C2FrameData::FLAG_END_OF_STREAM;
540 ALOGV("signalling eos");
541 }
542 work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
543 work->worklets.front()->output.buffers.clear();
544 work->worklets.front()->output.buffers.push_back(buffer);
545 work->worklets.front()->output.ordinal = work->input.ordinal;
546 work->workletsProcessed = 1u;
547 };
548 if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
549 fillWork(work);
550 } else {
551 finish(index, fillWork);
552 }
553}
554
555void C2SoftGav1Dec::process(const std::unique_ptr<C2Work> &work,
556 const std::shared_ptr<C2BlockPool> &pool) {
557 work->result = C2_OK;
558 work->workletsProcessed = 0u;
559 work->worklets.front()->output.configUpdate.clear();
560 work->worklets.front()->output.flags = work->input.flags;
561 if (mSignalledError || mSignalledOutputEos) {
562 work->result = C2_BAD_VALUE;
563 return;
564 }
565
566 size_t inOffset = 0u;
567 size_t inSize = 0u;
568 C2ReadView rView = mDummyReadView;
569 if (!work->input.buffers.empty()) {
570 rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
571 inSize = rView.capacity();
572 if (inSize && rView.error()) {
573 ALOGE("read view map failed %d", rView.error());
574 work->result = C2_CORRUPTED;
575 return;
576 }
577 }
578
579 bool codecConfig =
580 ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0);
581 bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
582
583 ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x", inSize,
584 (int)work->input.ordinal.timestamp.peeku(),
585 (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
586
587 if (codecConfig) {
588 fillEmptyWork(work);
589 return;
590 }
591
592 int64_t frameIndex = work->input.ordinal.frameIndex.peekll();
593 if (inSize) {
594 uint8_t *bitstream = const_cast<uint8_t *>(rView.data() + inOffset);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700595
Ray Essick24754942022-04-16 09:50:35 -0700596 mTimeStart = systemTime();
597 nsecs_t delay = mTimeStart - mTimeEnd;
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700598
599 const Libgav1StatusCode status =
James Zernb7aee6e2020-06-26 13:49:53 -0700600 mCodecCtx->EnqueueFrame(bitstream, inSize, frameIndex,
601 /*buffer_private_data=*/nullptr);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700602
Ray Essick24754942022-04-16 09:50:35 -0700603 mTimeEnd = systemTime();
604 nsecs_t decodeTime = mTimeEnd - mTimeStart;
605 ALOGV("decodeTime=%4" PRId64 " delay=%4" PRId64 "\n", decodeTime, delay);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700606
607 if (status != kLibgav1StatusOk) {
608 ALOGE("av1 decoder failed to decode frame. status: %d.", status);
609 work->result = C2_CORRUPTED;
610 work->workletsProcessed = 1u;
611 mSignalledError = true;
612 return;
613 }
614
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700615 }
616
617 (void)outputBuffer(pool, work);
618
619 if (eos) {
620 drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
621 mSignalledOutputEos = true;
622 } else if (!inSize) {
623 fillEmptyWork(work);
624 }
625}
626
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530627void C2SoftGav1Dec::getHDRStaticParams(const libgav1::DecoderBuffer *buffer,
628 const std::unique_ptr<C2Work> &work) {
629 C2StreamHdrStaticMetadataInfo::output hdrStaticMetadataInfo{};
630 bool infoPresent = false;
631 if (buffer->has_hdr_mdcv) {
632 // hdr_mdcv.primary_chromaticity_* values are in 0.16 fixed-point format.
633 hdrStaticMetadataInfo.mastering.red.x = buffer->hdr_mdcv.primary_chromaticity_x[0] / 65536.0;
634 hdrStaticMetadataInfo.mastering.red.y = buffer->hdr_mdcv.primary_chromaticity_y[0] / 65536.0;
635
636 hdrStaticMetadataInfo.mastering.green.x = buffer->hdr_mdcv.primary_chromaticity_x[1] / 65536.0;
637 hdrStaticMetadataInfo.mastering.green.y = buffer->hdr_mdcv.primary_chromaticity_y[1] / 65536.0;
638
639 hdrStaticMetadataInfo.mastering.blue.x = buffer->hdr_mdcv.primary_chromaticity_x[2] / 65536.0;
640 hdrStaticMetadataInfo.mastering.blue.y = buffer->hdr_mdcv.primary_chromaticity_y[2] / 65536.0;
641
642 // hdr_mdcv.white_point_chromaticity_* values are in 0.16 fixed-point format.
643 hdrStaticMetadataInfo.mastering.white.x = buffer->hdr_mdcv.white_point_chromaticity_x / 65536.0;
644 hdrStaticMetadataInfo.mastering.white.y = buffer->hdr_mdcv.white_point_chromaticity_y / 65536.0;
645
646 // hdr_mdcv.luminance_max is in 24.8 fixed-point format.
647 hdrStaticMetadataInfo.mastering.maxLuminance = buffer->hdr_mdcv.luminance_max / 256.0;
648 // hdr_mdcv.luminance_min is in 18.14 format.
649 hdrStaticMetadataInfo.mastering.minLuminance = buffer->hdr_mdcv.luminance_min / 16384.0;
650 infoPresent = true;
651 }
652
653 if (buffer->has_hdr_cll) {
654 hdrStaticMetadataInfo.maxCll = buffer->hdr_cll.max_cll;
655 hdrStaticMetadataInfo.maxFall = buffer->hdr_cll.max_fall;
656 infoPresent = true;
657 }
658 // config if static info has changed
659 if (infoPresent && !(hdrStaticMetadataInfo == mHdrStaticMetadataInfo)) {
660 mHdrStaticMetadataInfo = hdrStaticMetadataInfo;
661 work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(mHdrStaticMetadataInfo));
662 }
663}
664
665void C2SoftGav1Dec::getHDR10PlusInfoData(const libgav1::DecoderBuffer *buffer,
666 const std::unique_ptr<C2Work> &work) {
667 if (buffer->has_itut_t35) {
668 std::vector<uint8_t> payload;
669 size_t payloadSize = buffer->itut_t35.payload_size;
670 if (payloadSize > 0) {
671 payload.push_back(buffer->itut_t35.country_code);
672 if (buffer->itut_t35.country_code == 0xFF) {
673 payload.push_back(buffer->itut_t35.country_code_extension_byte);
674 }
675 payload.insert(payload.end(), buffer->itut_t35.payload_bytes,
676 buffer->itut_t35.payload_bytes + buffer->itut_t35.payload_size);
677 }
678
679 std::unique_ptr<C2StreamHdr10PlusInfo::output> hdr10PlusInfo =
680 C2StreamHdr10PlusInfo::output::AllocUnique(payload.size());
681 if (!hdr10PlusInfo) {
682 ALOGE("Hdr10PlusInfo allocation failed");
683 mSignalledError = true;
684 work->result = C2_NO_MEMORY;
685 return;
686 }
687 memcpy(hdr10PlusInfo->m.value, payload.data(), payload.size());
688
689 // config if hdr10Plus info has changed
690 if (nullptr == mHdr10PlusInfo || !(*hdr10PlusInfo == *mHdr10PlusInfo)) {
691 mHdr10PlusInfo = std::move(hdr10PlusInfo);
692 work->worklets.front()->output.configUpdate.push_back(std::move(mHdr10PlusInfo));
693 }
694 }
695}
696
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530697void C2SoftGav1Dec::getVuiParams(const libgav1::DecoderBuffer *buffer) {
698 VuiColorAspects vuiColorAspects;
699 vuiColorAspects.primaries = buffer->color_primary;
700 vuiColorAspects.transfer = buffer->transfer_characteristics;
701 vuiColorAspects.coeffs = buffer->matrix_coefficients;
702 vuiColorAspects.fullRange = buffer->color_range;
703
704 // convert vui aspects to C2 values if changed
705 if (!(vuiColorAspects == mBitstreamColorAspects)) {
706 mBitstreamColorAspects = vuiColorAspects;
707 ColorAspects sfAspects;
708 C2StreamColorAspectsInfo::input codedAspects = { 0u };
709 ColorUtils::convertIsoColorAspectsToCodecAspects(
710 vuiColorAspects.primaries, vuiColorAspects.transfer, vuiColorAspects.coeffs,
711 vuiColorAspects.fullRange, sfAspects);
712 if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) {
713 codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED;
714 }
715 if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) {
716 codedAspects.range = C2Color::RANGE_UNSPECIFIED;
717 }
718 if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) {
719 codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED;
720 }
721 if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) {
722 codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED;
723 }
724 std::vector<std::unique_ptr<C2SettingResult>> failures;
725 mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures);
726 }
727}
728
James Zernbcde4be2022-12-21 18:42:20 -0800729void C2SoftGav1Dec::setError(const std::unique_ptr<C2Work> &work, c2_status_t error) {
730 mSignalledError = true;
731 work->result = error;
732 work->workletsProcessed = 1u;
733}
734
735bool C2SoftGav1Dec::allocTmpFrameBuffer(size_t size) {
736 if (size > mTmpFrameBufferSize) {
737 mTmpFrameBuffer = std::make_unique<uint16_t[]>(size);
738 if (mTmpFrameBuffer == nullptr) {
739 mTmpFrameBufferSize = 0;
740 return false;
741 }
742 mTmpFrameBufferSize = size;
743 }
744 return true;
745}
746
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700747bool C2SoftGav1Dec::outputBuffer(const std::shared_ptr<C2BlockPool> &pool,
748 const std::unique_ptr<C2Work> &work) {
749 if (!(work && pool)) return false;
750
751 const libgav1::DecoderBuffer *buffer;
752 const Libgav1StatusCode status = mCodecCtx->DequeueFrame(&buffer);
753
James Zernb7aee6e2020-06-26 13:49:53 -0700754 if (status != kLibgav1StatusOk && status != kLibgav1StatusNothingToDequeue) {
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700755 ALOGE("av1 decoder DequeueFrame failed. status: %d.", status);
756 return false;
757 }
758
James Zernb7aee6e2020-06-26 13:49:53 -0700759 // |buffer| can be NULL if status was equal to kLibgav1StatusOk or
760 // kLibgav1StatusNothingToDequeue. This is not an error. This could mean one
761 // of two things:
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700762 // - The EnqueueFrame() call was either a flush (called with nullptr).
763 // - The enqueued frame did not have any displayable frames.
764 if (!buffer) {
765 return false;
766 }
767
768 const int width = buffer->displayed_width[0];
769 const int height = buffer->displayed_height[0];
770 if (width != mWidth || height != mHeight) {
771 mWidth = width;
772 mHeight = height;
773
774 C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
775 std::vector<std::unique_ptr<C2SettingResult>> failures;
776 c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
777 if (err == C2_OK) {
778 work->worklets.front()->output.configUpdate.push_back(
779 C2Param::Copy(size));
780 } else {
781 ALOGE("Config update size failed");
782 mSignalledError = true;
783 work->result = C2_CORRUPTED;
784 work->workletsProcessed = 1u;
785 return false;
786 }
787 }
788
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530789 getVuiParams(buffer);
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530790 getHDRStaticParams(buffer, work);
791 getHDR10PlusInfoData(buffer, work);
792
Vignesh Venkatasubramanianca7d1ab2021-02-04 12:39:06 -0800793 const bool isMonochrome =
794 buffer->image_format == libgav1::kImageFormatMonochrome400;
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700795
796 std::shared_ptr<C2GraphicBlock> block;
797 uint32_t format = HAL_PIXEL_FORMAT_YV12;
Lajos Molnar45109a32022-06-03 09:41:48 -0700798 std::shared_ptr<C2StreamColorAspectsInfo::output> codedColorAspects;
Harish Mahendrakar10c0c5d2022-05-30 20:35:16 -0700799 if (buffer->bitdepth == 10 && mPixelFormatInfo->value != HAL_PIXEL_FORMAT_YCBCR_420_888) {
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700800 IntfImpl::Lock lock = mIntf->lock();
Lajos Molnar45109a32022-06-03 09:41:48 -0700801 codedColorAspects = mIntf->getColorAspects_l();
Harish Mahendrakar749a74c2022-01-27 16:47:09 -0800802 bool allowRGBA1010102 = false;
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530803 if (codedColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
804 codedColorAspects->matrix == C2Color::MATRIX_BT2020 &&
805 codedColorAspects->transfer == C2Color::TRANSFER_ST2084) {
Harish Mahendrakar749a74c2022-01-27 16:47:09 -0800806 allowRGBA1010102 = true;
807 }
808 format = getHalPixelFormatForBitDepth10(allowRGBA1010102);
809 if ((format == HAL_PIXEL_FORMAT_RGBA_1010102) &&
810 (buffer->image_format != libgav1::kImageFormatYuv420)) {
Vignesh Venkatasubramanianca7d1ab2021-02-04 12:39:06 -0800811 ALOGE("Only YUV420 output is supported when targeting RGBA_1010102");
Harish Mahendrakar749a74c2022-01-27 16:47:09 -0800812 mSignalledError = true;
813 work->result = C2_OMITTED;
814 work->workletsProcessed = 1u;
815 return false;
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700816 }
817 }
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700818
819 if (mHalPixelFormat != format) {
820 C2StreamPixelFormatInfo::output pixelFormat(0u, format);
821 std::vector<std::unique_ptr<C2SettingResult>> failures;
822 c2_status_t err = mIntf->config({&pixelFormat }, C2_MAY_BLOCK, &failures);
823 if (err == C2_OK) {
824 work->worklets.front()->output.configUpdate.push_back(
825 C2Param::Copy(pixelFormat));
826 } else {
827 ALOGE("Config update pixelFormat failed");
828 mSignalledError = true;
829 work->workletsProcessed = 1u;
830 work->result = C2_CORRUPTED;
831 return UNKNOWN_ERROR;
832 }
833 mHalPixelFormat = format;
834 }
835
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700836 C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
837
Vignesh Venkatasubramanianc4d385f2022-02-22 10:49:46 -0800838 // We always create a graphic block that is width aligned to 16 and height
839 // aligned to 2. We set the correct "crop" value of the image in the call to
840 // createGraphicBuffer() by setting the correct image dimensions.
841 c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16),
842 align(mHeight, 2), format, usage,
843 &block);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700844
845 if (err != C2_OK) {
846 ALOGE("fetchGraphicBlock for Output failed with status %d", err);
847 work->result = err;
848 return false;
849 }
850
851 C2GraphicView wView = block->map().get();
852
853 if (wView.error()) {
854 ALOGE("graphic view map failed %d", wView.error());
855 work->result = C2_CORRUPTED;
856 return false;
857 }
858
859 ALOGV("provided (%dx%d) required (%dx%d), out frameindex %d", block->width(),
860 block->height(), mWidth, mHeight, (int)buffer->user_private_data);
861
ming.zhouac19c3d2019-10-11 11:14:07 +0800862 uint8_t *dstY = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_Y]);
863 uint8_t *dstU = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_U]);
864 uint8_t *dstV = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_V]);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700865
ming.zhouac19c3d2019-10-11 11:14:07 +0800866 C2PlanarLayout layout = wView.layout();
867 size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
Vignesh Venkatasubramanian47b1d222023-01-12 21:45:40 +0000868 size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
869 size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
ming.zhouac19c3d2019-10-11 11:14:07 +0800870
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700871 if (buffer->bitdepth == 10) {
872 const uint16_t *srcY = (const uint16_t *)buffer->plane[0];
873 const uint16_t *srcU = (const uint16_t *)buffer->plane[1];
874 const uint16_t *srcV = (const uint16_t *)buffer->plane[2];
James Zernbcde4be2022-12-21 18:42:20 -0800875 size_t srcYStride = buffer->stride[0] / 2;
876 size_t srcUStride = buffer->stride[1] / 2;
877 size_t srcVStride = buffer->stride[2] / 2;
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700878
879 if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
Lajos Molnar45109a32022-06-03 09:41:48 -0700880 convertYUV420Planar16ToY410OrRGBA1010102(
James Zernbcde4be2022-12-21 18:42:20 -0800881 (uint32_t *)dstY, srcY, srcU, srcV, srcYStride,
882 srcUStride, srcVStride,
Lajos Molnar45109a32022-06-03 09:41:48 -0700883 dstYStride / sizeof(uint32_t), mWidth, mHeight,
884 std::static_pointer_cast<const C2ColorAspectsStruct>(codedColorAspects));
Harish Mahendrakar1b1aef22021-12-30 19:12:51 -0800885 } else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
James Zernbcde4be2022-12-21 18:42:20 -0800886 dstYStride /= 2;
887 dstUStride /= 2;
888 dstVStride /= 2;
889 if (buffer->image_format == libgav1::kImageFormatYuv444 ||
890 buffer->image_format == libgav1::kImageFormatYuv422) {
891 // TODO(https://crbug.com/libyuv/952): replace this block with libyuv::I410ToP010 and
892 // libyuv::I210ToP010 when they are available.
893 // Note it may be safe to alias dstY in I010ToP010, but the libyuv API doesn't make any
894 // guarantees.
895 const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
896 if (!allocTmpFrameBuffer(tmpSize)) {
897 ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
898 setError(work, C2_NO_MEMORY);
899 return false;
900 }
901 uint16_t *const tmpY = mTmpFrameBuffer.get();
902 uint16_t *const tmpU = tmpY + dstYStride * mHeight;
903 uint16_t *const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
904 if (buffer->image_format == libgav1::kImageFormatYuv444) {
905 libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
906 tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride,
907 mWidth, mHeight);
908 } else {
909 libyuv::I210ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
910 tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride,
911 mWidth, mHeight);
912 }
913 libyuv::I010ToP010(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstVStride,
914 (uint16_t*)dstY, dstYStride, (uint16_t*)dstU, dstUStride,
915 mWidth, mHeight);
916 } else {
917 convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
918 srcYStride, srcUStride, srcVStride, dstYStride,
919 dstUStride, mWidth, mHeight, isMonochrome);
920 }
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700921 } else {
James Zernbcde4be2022-12-21 18:42:20 -0800922 if (buffer->image_format == libgav1::kImageFormatYuv444) {
923 // TODO(https://crbug.com/libyuv/950): replace this block with libyuv::I410ToI420 when
924 // it's available.
925 const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
926 if (!allocTmpFrameBuffer(tmpSize)) {
927 ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
928 setError(work, C2_NO_MEMORY);
929 return false;
930 }
931 uint16_t *const tmpY = mTmpFrameBuffer.get();
932 uint16_t *const tmpU = tmpY + dstYStride * mHeight;
933 uint16_t *const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
934 libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
935 tmpY, dstYStride, tmpU, dstUStride, tmpV, dstVStride,
936 mWidth, mHeight);
937 libyuv::I010ToI420(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride,
938 dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
939 mWidth, mHeight);
940 } else if (buffer->image_format == libgav1::kImageFormatYuv422) {
941 libyuv::I210ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
942 dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
943 mWidth, mHeight);
944 } else {
945 convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
946 srcUStride / 2, srcVStride / 2, dstYStride, dstUStride,
947 mWidth, mHeight, isMonochrome);
948 }
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700949 }
950 } else {
951 const uint8_t *srcY = (const uint8_t *)buffer->plane[0];
952 const uint8_t *srcU = (const uint8_t *)buffer->plane[1];
953 const uint8_t *srcV = (const uint8_t *)buffer->plane[2];
James Zernbcde4be2022-12-21 18:42:20 -0800954 size_t srcYStride = buffer->stride[0];
955 size_t srcUStride = buffer->stride[1];
956 size_t srcVStride = buffer->stride[2];
Vignesh Venkatasubramanian406ed312022-04-21 10:32:55 -0700957
958 if (buffer->image_format == libgav1::kImageFormatYuv444) {
959 libyuv::I444ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
960 dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
961 mWidth, mHeight);
962 } else if (buffer->image_format == libgav1::kImageFormatYuv422) {
963 libyuv::I422ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
964 dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
965 mWidth, mHeight);
966 } else {
967 convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
968 srcVStride, dstYStride, dstUStride, dstVStride, mWidth, mHeight,
969 isMonochrome);
970 }
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700971 }
972 finishWork(buffer->user_private_data, work, std::move(block));
973 block = nullptr;
974 return true;
975}
976
977c2_status_t C2SoftGav1Dec::drainInternal(
978 uint32_t drainMode, const std::shared_ptr<C2BlockPool> &pool,
979 const std::unique_ptr<C2Work> &work) {
980 if (drainMode == NO_DRAIN) {
981 ALOGW("drain with NO_DRAIN: no-op");
982 return C2_OK;
983 }
984 if (drainMode == DRAIN_CHAIN) {
985 ALOGW("DRAIN_CHAIN not supported");
986 return C2_OMITTED;
987 }
988
James Zernb7aee6e2020-06-26 13:49:53 -0700989 const Libgav1StatusCode status = mCodecCtx->SignalEOS();
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700990 if (status != kLibgav1StatusOk) {
991 ALOGE("Failed to flush av1 decoder. status: %d.", status);
992 return C2_CORRUPTED;
993 }
994
995 while (outputBuffer(pool, work)) {
996 }
997
998 if (drainMode == DRAIN_COMPONENT_WITH_EOS && work &&
999 work->workletsProcessed == 0u) {
1000 fillEmptyWork(work);
1001 }
1002
1003 return C2_OK;
1004}
1005
1006c2_status_t C2SoftGav1Dec::drain(uint32_t drainMode,
1007 const std::shared_ptr<C2BlockPool> &pool) {
1008 return drainInternal(drainMode, pool, nullptr);
1009}
1010
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -07001011class C2SoftGav1Factory : public C2ComponentFactory {
1012 public:
1013 C2SoftGav1Factory()
1014 : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
1015 GetCodec2PlatformComponentStore()->getParamReflector())) {}
1016
1017 virtual c2_status_t createComponent(
1018 c2_node_id_t id, std::shared_ptr<C2Component> *const component,
1019 std::function<void(C2Component *)> deleter) override {
1020 *component = std::shared_ptr<C2Component>(
1021 new C2SoftGav1Dec(COMPONENT_NAME, id,
1022 std::make_shared<C2SoftGav1Dec::IntfImpl>(mHelper)),
1023 deleter);
1024 return C2_OK;
1025 }
1026
1027 virtual c2_status_t createInterface(
1028 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *const interface,
1029 std::function<void(C2ComponentInterface *)> deleter) override {
1030 *interface = std::shared_ptr<C2ComponentInterface>(
1031 new SimpleInterface<C2SoftGav1Dec::IntfImpl>(
1032 COMPONENT_NAME, id,
1033 std::make_shared<C2SoftGav1Dec::IntfImpl>(mHelper)),
1034 deleter);
1035 return C2_OK;
1036 }
1037
1038 virtual ~C2SoftGav1Factory() override = default;
1039
1040 private:
1041 std::shared_ptr<C2ReflectorHelper> mHelper;
1042};
1043
1044} // namespace android
1045
Cindy Zhouf6c0c3c2020-12-02 10:53:40 -08001046__attribute__((cfi_canonical_jump_table))
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -07001047extern "C" ::C2ComponentFactory *CreateCodec2Factory() {
1048 ALOGV("in %s", __func__);
1049 return new ::android::C2SoftGav1Factory();
1050}
1051
Cindy Zhouf6c0c3c2020-12-02 10:53:40 -08001052__attribute__((cfi_canonical_jump_table))
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -07001053extern "C" void DestroyCodec2Factory(::C2ComponentFactory *factory) {
1054 ALOGV("in %s", __func__);
1055 delete factory;
1056}