blob: 60031fe315f9c83c6c393377b9bbfb018784a595 [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
36class C2SoftGav1Dec::IntfImpl : public SimpleInterface<void>::BaseParams {
37 public:
38 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
39 : SimpleInterface<void>::BaseParams(
40 helper, COMPONENT_NAME, C2Component::KIND_DECODER,
41 C2Component::DOMAIN_VIDEO, MEDIA_MIMETYPE_VIDEO_AV1) {
42 noPrivateBuffers(); // TODO: account for our buffers here.
43 noInputReferences();
44 noOutputReferences();
45 noInputLatency();
46 noTimeStretch();
47
48 addParameter(DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
49 .withConstValue(new C2ComponentAttributesSetting(
50 C2Component::ATTRIB_IS_TEMPORAL))
51 .build());
52
53 addParameter(
54 DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
55 .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
56 .withFields({
Vignesh Venkatasubramanian2d8d4702021-01-25 09:42:44 -080057 C2F(mSize, width).inRange(2, 4096, 2),
58 C2F(mSize, height).inRange(2, 4096, 2),
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -070059 })
60 .withSetter(SizeSetter)
61 .build());
62
63 addParameter(DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
64 .withDefault(new C2StreamProfileLevelInfo::input(
65 0u, C2Config::PROFILE_AV1_0, C2Config::LEVEL_AV1_2_1))
66 .withFields({C2F(mProfileLevel, profile)
67 .oneOf({C2Config::PROFILE_AV1_0,
68 C2Config::PROFILE_AV1_1}),
69 C2F(mProfileLevel, level)
70 .oneOf({
Harish Mahendrakar1ad8c3b2021-06-04 15:42:31 -070071 C2Config::LEVEL_AV1_2, C2Config::LEVEL_AV1_2_1,
72 C2Config::LEVEL_AV1_2_2, C2Config::LEVEL_AV1_2_3,
73 C2Config::LEVEL_AV1_3, C2Config::LEVEL_AV1_3_1,
74 C2Config::LEVEL_AV1_3_2, C2Config::LEVEL_AV1_3_3,
75 C2Config::LEVEL_AV1_4, C2Config::LEVEL_AV1_4_1,
76 C2Config::LEVEL_AV1_4_2, C2Config::LEVEL_AV1_4_3,
77 C2Config::LEVEL_AV1_5, C2Config::LEVEL_AV1_5_1,
78 C2Config::LEVEL_AV1_5_2, C2Config::LEVEL_AV1_5_3,
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -070079 })})
80 .withSetter(ProfileLevelSetter, mSize)
81 .build());
82
83 mHdr10PlusInfoInput = C2StreamHdr10PlusInfo::input::AllocShared(0);
84 addParameter(
85 DefineParam(mHdr10PlusInfoInput, C2_PARAMKEY_INPUT_HDR10_PLUS_INFO)
86 .withDefault(mHdr10PlusInfoInput)
87 .withFields({
88 C2F(mHdr10PlusInfoInput, m.value).any(),
89 })
90 .withSetter(Hdr10PlusInfoInputSetter)
91 .build());
92
93 mHdr10PlusInfoOutput = C2StreamHdr10PlusInfo::output::AllocShared(0);
94 addParameter(
95 DefineParam(mHdr10PlusInfoOutput, C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO)
96 .withDefault(mHdr10PlusInfoOutput)
97 .withFields({
98 C2F(mHdr10PlusInfoOutput, m.value).any(),
99 })
100 .withSetter(Hdr10PlusInfoOutputSetter)
101 .build());
102
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530103 // default static info
104 C2HdrStaticMetadataStruct defaultStaticInfo{};
105 helper->addStructDescriptors<C2MasteringDisplayColorVolumeStruct, C2ColorXyStruct>();
106 addParameter(
107 DefineParam(mHdrStaticInfo, C2_PARAMKEY_HDR_STATIC_INFO)
108 .withDefault(new C2StreamHdrStaticInfo::output(0u, defaultStaticInfo))
109 .withFields({
110 C2F(mHdrStaticInfo, mastering.red.x).inRange(0, 1),
111 C2F(mHdrStaticInfo, mastering.red.y).inRange(0, 1),
112 C2F(mHdrStaticInfo, mastering.green.x).inRange(0, 1),
113 C2F(mHdrStaticInfo, mastering.green.y).inRange(0, 1),
114 C2F(mHdrStaticInfo, mastering.blue.x).inRange(0, 1),
115 C2F(mHdrStaticInfo, mastering.blue.y).inRange(0, 1),
116 C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
117 C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
118 C2F(mHdrStaticInfo, mastering.maxLuminance).inRange(0, 65535),
119 C2F(mHdrStaticInfo, mastering.minLuminance).inRange(0, 6.5535),
120 C2F(mHdrStaticInfo, maxCll).inRange(0, 0XFFFF),
121 C2F(mHdrStaticInfo, maxFall).inRange(0, 0XFFFF)
122 })
123 .withSetter(HdrStaticInfoSetter)
124 .build());
125
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700126 addParameter(
127 DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
128 .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240))
129 .withFields({
130 C2F(mSize, width).inRange(2, 2048, 2),
131 C2F(mSize, height).inRange(2, 2048, 2),
132 })
133 .withSetter(MaxPictureSizeSetter, mSize)
134 .build());
135
136 addParameter(DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
137 .withDefault(new C2StreamMaxBufferSizeInfo::input(
138 0u, 320 * 240 * 3 / 4))
139 .withFields({
140 C2F(mMaxInputSize, value).any(),
141 })
142 .calculatedAs(MaxInputSizeSetter, mMaxSize)
143 .build());
144
145 C2ChromaOffsetStruct locations[1] = {C2ChromaOffsetStruct::ITU_YUV_420_0()};
146 std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
147 C2StreamColorInfo::output::AllocShared(1u, 0u, 8u /* bitDepth */,
148 C2Color::YUV_420);
149 memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
150
151 defaultColorInfo = C2StreamColorInfo::output::AllocShared(
152 {C2ChromaOffsetStruct::ITU_YUV_420_0()}, 0u, 8u /* bitDepth */,
153 C2Color::YUV_420);
154 helper->addStructDescriptors<C2ChromaOffsetStruct>();
155
156 addParameter(DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
157 .withConstValue(defaultColorInfo)
158 .build());
159
160 addParameter(
161 DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
162 .withDefault(new C2StreamColorAspectsTuning::output(
163 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
164 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
165 .withFields(
166 {C2F(mDefaultColorAspects, range)
167 .inRange(C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
168 C2F(mDefaultColorAspects, primaries)
169 .inRange(C2Color::PRIMARIES_UNSPECIFIED,
170 C2Color::PRIMARIES_OTHER),
171 C2F(mDefaultColorAspects, transfer)
172 .inRange(C2Color::TRANSFER_UNSPECIFIED,
173 C2Color::TRANSFER_OTHER),
174 C2F(mDefaultColorAspects, matrix)
175 .inRange(C2Color::MATRIX_UNSPECIFIED,
176 C2Color::MATRIX_OTHER)})
177 .withSetter(DefaultColorAspectsSetter)
178 .build());
179
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530180 addParameter(
181 DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
182 .withDefault(new C2StreamColorAspectsInfo::input(
183 0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
184 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
185 .withFields({
186 C2F(mCodedColorAspects, range).inRange(
187 C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
188 C2F(mCodedColorAspects, primaries).inRange(
189 C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
190 C2F(mCodedColorAspects, transfer).inRange(
191 C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
192 C2F(mCodedColorAspects, matrix).inRange(
193 C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
194 })
195 .withSetter(CodedColorAspectsSetter)
196 .build());
197
198 addParameter(
199 DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
200 .withDefault(new C2StreamColorAspectsInfo::output(
201 0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
202 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
203 .withFields({
204 C2F(mColorAspects, range).inRange(
205 C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
206 C2F(mColorAspects, primaries).inRange(
207 C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
208 C2F(mColorAspects, transfer).inRange(
209 C2Color::TRANSFER_UNSPECIFIED, C2Color::TRANSFER_OTHER),
210 C2F(mColorAspects, matrix).inRange(
211 C2Color::MATRIX_UNSPECIFIED, C2Color::MATRIX_OTHER)
212 })
213 .withSetter(ColorAspectsSetter, mDefaultColorAspects, mCodedColorAspects)
214 .build());
215
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700216 std::vector<uint32_t> pixelFormats = {HAL_PIXEL_FORMAT_YCBCR_420_888};
Harish Mahendrakarf5dec502022-04-13 15:53:55 -0700217 if (isHalPixelFormatSupported((AHardwareBuffer_Format)HAL_PIXEL_FORMAT_YCBCR_P010)) {
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700218 pixelFormats.push_back(HAL_PIXEL_FORMAT_YCBCR_P010);
219 }
Harish Mahendrakar10c0c5d2022-05-30 20:35:16 -0700220 // If color format surface isn't added to supported formats, there is no way to know
221 // when the color-format is configured to surface. This is necessary to be able to
222 // choose 10-bit format while decoding 10-bit clips in surface mode.
223 pixelFormats.push_back(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
224
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700225 // TODO: support more formats?
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700226 addParameter(
227 DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
228 .withDefault(new C2StreamPixelFormatInfo::output(
229 0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
230 .withFields({C2F(mPixelFormat, value).oneOf(pixelFormats)})
231 .withSetter((Setter<decltype(*mPixelFormat)>::StrictValueWithNoDeps))
232 .build());
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700233 }
234
235 static C2R SizeSetter(bool mayBlock,
236 const C2P<C2StreamPictureSizeInfo::output> &oldMe,
237 C2P<C2StreamPictureSizeInfo::output> &me) {
238 (void)mayBlock;
239 C2R res = C2R::Ok();
240 if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
241 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
242 me.set().width = oldMe.v.width;
243 }
244 if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
245 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
246 me.set().height = oldMe.v.height;
247 }
248 return res;
249 }
250
251 static C2R MaxPictureSizeSetter(
252 bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output> &me,
253 const C2P<C2StreamPictureSizeInfo::output> &size) {
254 (void)mayBlock;
255 // TODO: get max width/height from the size's field helpers vs.
256 // hardcoding
257 me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4096u);
258 me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4096u);
259 return C2R::Ok();
260 }
261
262 static C2R MaxInputSizeSetter(
263 bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me,
264 const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
265 (void)mayBlock;
266 // assume compression ratio of 2
267 me.set().value =
268 (((maxSize.v.width + 63) / 64) * ((maxSize.v.height + 63) / 64) * 3072);
269 return C2R::Ok();
270 }
271
272 static C2R DefaultColorAspectsSetter(
273 bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) {
274 (void)mayBlock;
275 if (me.v.range > C2Color::RANGE_OTHER) {
276 me.set().range = C2Color::RANGE_OTHER;
277 }
278 if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
279 me.set().primaries = C2Color::PRIMARIES_OTHER;
280 }
281 if (me.v.transfer > C2Color::TRANSFER_OTHER) {
282 me.set().transfer = C2Color::TRANSFER_OTHER;
283 }
284 if (me.v.matrix > C2Color::MATRIX_OTHER) {
285 me.set().matrix = C2Color::MATRIX_OTHER;
286 }
287 return C2R::Ok();
288 }
289
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530290 static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input> &me) {
291 (void)mayBlock;
292 if (me.v.range > C2Color::RANGE_OTHER) {
293 me.set().range = C2Color::RANGE_OTHER;
294 }
295 if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
296 me.set().primaries = C2Color::PRIMARIES_OTHER;
297 }
298 if (me.v.transfer > C2Color::TRANSFER_OTHER) {
299 me.set().transfer = C2Color::TRANSFER_OTHER;
300 }
301 if (me.v.matrix > C2Color::MATRIX_OTHER) {
302 me.set().matrix = C2Color::MATRIX_OTHER;
303 }
304 return C2R::Ok();
305 }
306
307 static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
308 const C2P<C2StreamColorAspectsTuning::output> &def,
309 const C2P<C2StreamColorAspectsInfo::input> &coded) {
310 (void)mayBlock;
311 // take default values for all unspecified fields, and coded values for specified ones
312 me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range;
313 me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED
314 ? def.v.primaries : coded.v.primaries;
315 me.set().transfer = coded.v.transfer == TRANSFER_UNSPECIFIED
316 ? def.v.transfer : coded.v.transfer;
317 me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix : coded.v.matrix;
318 return C2R::Ok();
319 }
320
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700321 static C2R ProfileLevelSetter(
322 bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
323 const C2P<C2StreamPictureSizeInfo::output> &size) {
324 (void)mayBlock;
325 (void)size;
326 (void)me; // TODO: validate
327 return C2R::Ok();
328 }
329
330 std::shared_ptr<C2StreamColorAspectsTuning::output>
331 getDefaultColorAspects_l() {
332 return mDefaultColorAspects;
333 }
334
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530335 std::shared_ptr<C2StreamColorAspectsInfo::output> getColorAspects_l() {
336 return mColorAspects;
337 }
338
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700339 static C2R Hdr10PlusInfoInputSetter(bool mayBlock,
340 C2P<C2StreamHdr10PlusInfo::input> &me) {
341 (void)mayBlock;
342 (void)me; // TODO: validate
343 return C2R::Ok();
344 }
345
346 static C2R Hdr10PlusInfoOutputSetter(bool mayBlock,
347 C2P<C2StreamHdr10PlusInfo::output> &me) {
348 (void)mayBlock;
349 (void)me; // TODO: validate
350 return C2R::Ok();
351 }
352
Harish Mahendrakar10c0c5d2022-05-30 20:35:16 -0700353 // unsafe getters
354 std::shared_ptr<C2StreamPixelFormatInfo::output> getPixelFormat_l() const { return mPixelFormat; }
355
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530356 static C2R HdrStaticInfoSetter(bool mayBlock, C2P<C2StreamHdrStaticInfo::output> &me) {
357 (void)mayBlock;
358 if (me.v.mastering.red.x > 1) {
359 me.set().mastering.red.x = 1;
360 }
361 if (me.v.mastering.red.y > 1) {
362 me.set().mastering.red.y = 1;
363 }
364 if (me.v.mastering.green.x > 1) {
365 me.set().mastering.green.x = 1;
366 }
367 if (me.v.mastering.green.y > 1) {
368 me.set().mastering.green.y = 1;
369 }
370 if (me.v.mastering.blue.x > 1) {
371 me.set().mastering.blue.x = 1;
372 }
373 if (me.v.mastering.blue.y > 1) {
374 me.set().mastering.blue.y = 1;
375 }
376 if (me.v.mastering.white.x > 1) {
377 me.set().mastering.white.x = 1;
378 }
379 if (me.v.mastering.white.y > 1) {
380 me.set().mastering.white.y = 1;
381 }
382 if (me.v.mastering.maxLuminance > 65535.0) {
383 me.set().mastering.maxLuminance = 65535.0;
384 }
385 if (me.v.mastering.minLuminance > 6.5535) {
386 me.set().mastering.minLuminance = 6.5535;
387 }
388 if (me.v.maxCll > 65535.0) {
389 me.set().maxCll = 65535.0;
390 }
391 if (me.v.maxFall > 65535.0) {
392 me.set().maxFall = 65535.0;
393 }
394 return C2R::Ok();
395 }
396
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700397 private:
398 std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
399 std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
400 std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize;
401 std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize;
402 std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
403 std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
404 std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530405 std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects;
406 std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700407 std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput;
408 std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput;
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530409 std::shared_ptr<C2StreamHdrStaticInfo::output> mHdrStaticInfo;
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700410};
411
412C2SoftGav1Dec::C2SoftGav1Dec(const char *name, c2_node_id_t id,
413 const std::shared_ptr<IntfImpl> &intfImpl)
414 : SimpleC2Component(
415 std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700416 mIntf(intfImpl),
417 mCodecCtx(nullptr) {
418 gettimeofday(&mTimeStart, nullptr);
419 gettimeofday(&mTimeEnd, nullptr);
420}
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);
594 int32_t decodeTime = 0;
595 int32_t delay = 0;
596
597 GETTIME(&mTimeStart, nullptr);
598 TIME_DIFF(mTimeEnd, mTimeStart, delay);
599
600 const Libgav1StatusCode status =
James Zernb7aee6e2020-06-26 13:49:53 -0700601 mCodecCtx->EnqueueFrame(bitstream, inSize, frameIndex,
602 /*buffer_private_data=*/nullptr);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700603
604 GETTIME(&mTimeEnd, nullptr);
605 TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
606 ALOGV("decodeTime=%4d delay=%4d\n", decodeTime, delay);
607
608 if (status != kLibgav1StatusOk) {
609 ALOGE("av1 decoder failed to decode frame. status: %d.", status);
610 work->result = C2_CORRUPTED;
611 work->workletsProcessed = 1u;
612 mSignalledError = true;
613 return;
614 }
615
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700616 }
617
618 (void)outputBuffer(pool, work);
619
620 if (eos) {
621 drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
622 mSignalledOutputEos = true;
623 } else if (!inSize) {
624 fillEmptyWork(work);
625 }
626}
627
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530628void C2SoftGav1Dec::getHDRStaticParams(const libgav1::DecoderBuffer *buffer,
629 const std::unique_ptr<C2Work> &work) {
630 C2StreamHdrStaticMetadataInfo::output hdrStaticMetadataInfo{};
631 bool infoPresent = false;
632 if (buffer->has_hdr_mdcv) {
633 // hdr_mdcv.primary_chromaticity_* values are in 0.16 fixed-point format.
634 hdrStaticMetadataInfo.mastering.red.x = buffer->hdr_mdcv.primary_chromaticity_x[0] / 65536.0;
635 hdrStaticMetadataInfo.mastering.red.y = buffer->hdr_mdcv.primary_chromaticity_y[0] / 65536.0;
636
637 hdrStaticMetadataInfo.mastering.green.x = buffer->hdr_mdcv.primary_chromaticity_x[1] / 65536.0;
638 hdrStaticMetadataInfo.mastering.green.y = buffer->hdr_mdcv.primary_chromaticity_y[1] / 65536.0;
639
640 hdrStaticMetadataInfo.mastering.blue.x = buffer->hdr_mdcv.primary_chromaticity_x[2] / 65536.0;
641 hdrStaticMetadataInfo.mastering.blue.y = buffer->hdr_mdcv.primary_chromaticity_y[2] / 65536.0;
642
643 // hdr_mdcv.white_point_chromaticity_* values are in 0.16 fixed-point format.
644 hdrStaticMetadataInfo.mastering.white.x = buffer->hdr_mdcv.white_point_chromaticity_x / 65536.0;
645 hdrStaticMetadataInfo.mastering.white.y = buffer->hdr_mdcv.white_point_chromaticity_y / 65536.0;
646
647 // hdr_mdcv.luminance_max is in 24.8 fixed-point format.
648 hdrStaticMetadataInfo.mastering.maxLuminance = buffer->hdr_mdcv.luminance_max / 256.0;
649 // hdr_mdcv.luminance_min is in 18.14 format.
650 hdrStaticMetadataInfo.mastering.minLuminance = buffer->hdr_mdcv.luminance_min / 16384.0;
651 infoPresent = true;
652 }
653
654 if (buffer->has_hdr_cll) {
655 hdrStaticMetadataInfo.maxCll = buffer->hdr_cll.max_cll;
656 hdrStaticMetadataInfo.maxFall = buffer->hdr_cll.max_fall;
657 infoPresent = true;
658 }
659 // config if static info has changed
660 if (infoPresent && !(hdrStaticMetadataInfo == mHdrStaticMetadataInfo)) {
661 mHdrStaticMetadataInfo = hdrStaticMetadataInfo;
662 work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(mHdrStaticMetadataInfo));
663 }
664}
665
666void C2SoftGav1Dec::getHDR10PlusInfoData(const libgav1::DecoderBuffer *buffer,
667 const std::unique_ptr<C2Work> &work) {
668 if (buffer->has_itut_t35) {
669 std::vector<uint8_t> payload;
670 size_t payloadSize = buffer->itut_t35.payload_size;
671 if (payloadSize > 0) {
672 payload.push_back(buffer->itut_t35.country_code);
673 if (buffer->itut_t35.country_code == 0xFF) {
674 payload.push_back(buffer->itut_t35.country_code_extension_byte);
675 }
676 payload.insert(payload.end(), buffer->itut_t35.payload_bytes,
677 buffer->itut_t35.payload_bytes + buffer->itut_t35.payload_size);
678 }
679
680 std::unique_ptr<C2StreamHdr10PlusInfo::output> hdr10PlusInfo =
681 C2StreamHdr10PlusInfo::output::AllocUnique(payload.size());
682 if (!hdr10PlusInfo) {
683 ALOGE("Hdr10PlusInfo allocation failed");
684 mSignalledError = true;
685 work->result = C2_NO_MEMORY;
686 return;
687 }
688 memcpy(hdr10PlusInfo->m.value, payload.data(), payload.size());
689
690 // config if hdr10Plus info has changed
691 if (nullptr == mHdr10PlusInfo || !(*hdr10PlusInfo == *mHdr10PlusInfo)) {
692 mHdr10PlusInfo = std::move(hdr10PlusInfo);
693 work->worklets.front()->output.configUpdate.push_back(std::move(mHdr10PlusInfo));
694 }
695 }
696}
697
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530698void C2SoftGav1Dec::getVuiParams(const libgav1::DecoderBuffer *buffer) {
699 VuiColorAspects vuiColorAspects;
700 vuiColorAspects.primaries = buffer->color_primary;
701 vuiColorAspects.transfer = buffer->transfer_characteristics;
702 vuiColorAspects.coeffs = buffer->matrix_coefficients;
703 vuiColorAspects.fullRange = buffer->color_range;
704
705 // convert vui aspects to C2 values if changed
706 if (!(vuiColorAspects == mBitstreamColorAspects)) {
707 mBitstreamColorAspects = vuiColorAspects;
708 ColorAspects sfAspects;
709 C2StreamColorAspectsInfo::input codedAspects = { 0u };
710 ColorUtils::convertIsoColorAspectsToCodecAspects(
711 vuiColorAspects.primaries, vuiColorAspects.transfer, vuiColorAspects.coeffs,
712 vuiColorAspects.fullRange, sfAspects);
713 if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) {
714 codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED;
715 }
716 if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) {
717 codedAspects.range = C2Color::RANGE_UNSPECIFIED;
718 }
719 if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) {
720 codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED;
721 }
722 if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) {
723 codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED;
724 }
725 std::vector<std::unique_ptr<C2SettingResult>> failures;
726 mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures);
727 }
728}
729
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700730bool C2SoftGav1Dec::outputBuffer(const std::shared_ptr<C2BlockPool> &pool,
731 const std::unique_ptr<C2Work> &work) {
732 if (!(work && pool)) return false;
733
734 const libgav1::DecoderBuffer *buffer;
735 const Libgav1StatusCode status = mCodecCtx->DequeueFrame(&buffer);
736
James Zernb7aee6e2020-06-26 13:49:53 -0700737 if (status != kLibgav1StatusOk && status != kLibgav1StatusNothingToDequeue) {
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700738 ALOGE("av1 decoder DequeueFrame failed. status: %d.", status);
739 return false;
740 }
741
James Zernb7aee6e2020-06-26 13:49:53 -0700742 // |buffer| can be NULL if status was equal to kLibgav1StatusOk or
743 // kLibgav1StatusNothingToDequeue. This is not an error. This could mean one
744 // of two things:
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700745 // - The EnqueueFrame() call was either a flush (called with nullptr).
746 // - The enqueued frame did not have any displayable frames.
747 if (!buffer) {
748 return false;
749 }
750
751 const int width = buffer->displayed_width[0];
752 const int height = buffer->displayed_height[0];
753 if (width != mWidth || height != mHeight) {
754 mWidth = width;
755 mHeight = height;
756
757 C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
758 std::vector<std::unique_ptr<C2SettingResult>> failures;
759 c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
760 if (err == C2_OK) {
761 work->worklets.front()->output.configUpdate.push_back(
762 C2Param::Copy(size));
763 } else {
764 ALOGE("Config update size failed");
765 mSignalledError = true;
766 work->result = C2_CORRUPTED;
767 work->workletsProcessed = 1u;
768 return false;
769 }
770 }
771
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530772 getVuiParams(buffer);
Manisha Jajoo210d52e2022-05-19 17:11:55 +0530773 getHDRStaticParams(buffer, work);
774 getHDR10PlusInfoData(buffer, work);
775
James Zern4d25d652021-06-22 18:10:13 -0700776 if (!(buffer->image_format == libgav1::kImageFormatYuv420 ||
777 buffer->image_format == libgav1::kImageFormatMonochrome400)) {
778 ALOGE("image_format %d not supported", buffer->image_format);
779 mSignalledError = true;
780 work->workletsProcessed = 1u;
781 work->result = C2_CORRUPTED;
782 return false;
783 }
Vignesh Venkatasubramanianca7d1ab2021-02-04 12:39:06 -0800784 const bool isMonochrome =
785 buffer->image_format == libgav1::kImageFormatMonochrome400;
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700786
787 std::shared_ptr<C2GraphicBlock> block;
788 uint32_t format = HAL_PIXEL_FORMAT_YV12;
Lajos Molnar45109a32022-06-03 09:41:48 -0700789 std::shared_ptr<C2StreamColorAspectsInfo::output> codedColorAspects;
Harish Mahendrakar10c0c5d2022-05-30 20:35:16 -0700790 if (buffer->bitdepth == 10 && mPixelFormatInfo->value != HAL_PIXEL_FORMAT_YCBCR_420_888) {
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700791 IntfImpl::Lock lock = mIntf->lock();
Lajos Molnar45109a32022-06-03 09:41:48 -0700792 codedColorAspects = mIntf->getColorAspects_l();
Harish Mahendrakar749a74c2022-01-27 16:47:09 -0800793 bool allowRGBA1010102 = false;
Neelkamal Semwalc13a76a2021-09-01 17:07:30 +0530794 if (codedColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
795 codedColorAspects->matrix == C2Color::MATRIX_BT2020 &&
796 codedColorAspects->transfer == C2Color::TRANSFER_ST2084) {
Harish Mahendrakar749a74c2022-01-27 16:47:09 -0800797 allowRGBA1010102 = true;
798 }
799 format = getHalPixelFormatForBitDepth10(allowRGBA1010102);
800 if ((format == HAL_PIXEL_FORMAT_RGBA_1010102) &&
801 (buffer->image_format != libgav1::kImageFormatYuv420)) {
Vignesh Venkatasubramanianca7d1ab2021-02-04 12:39:06 -0800802 ALOGE("Only YUV420 output is supported when targeting RGBA_1010102");
Harish Mahendrakar749a74c2022-01-27 16:47:09 -0800803 mSignalledError = true;
804 work->result = C2_OMITTED;
805 work->workletsProcessed = 1u;
806 return false;
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700807 }
808 }
Harish Mahendrakard4bbb762022-03-29 11:53:23 -0700809
810 if (mHalPixelFormat != format) {
811 C2StreamPixelFormatInfo::output pixelFormat(0u, format);
812 std::vector<std::unique_ptr<C2SettingResult>> failures;
813 c2_status_t err = mIntf->config({&pixelFormat }, C2_MAY_BLOCK, &failures);
814 if (err == C2_OK) {
815 work->worklets.front()->output.configUpdate.push_back(
816 C2Param::Copy(pixelFormat));
817 } else {
818 ALOGE("Config update pixelFormat failed");
819 mSignalledError = true;
820 work->workletsProcessed = 1u;
821 work->result = C2_CORRUPTED;
822 return UNKNOWN_ERROR;
823 }
824 mHalPixelFormat = format;
825 }
826
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700827 C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
828
829 c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16), mHeight, format,
830 usage, &block);
831
832 if (err != C2_OK) {
833 ALOGE("fetchGraphicBlock for Output failed with status %d", err);
834 work->result = err;
835 return false;
836 }
837
838 C2GraphicView wView = block->map().get();
839
840 if (wView.error()) {
841 ALOGE("graphic view map failed %d", wView.error());
842 work->result = C2_CORRUPTED;
843 return false;
844 }
845
846 ALOGV("provided (%dx%d) required (%dx%d), out frameindex %d", block->width(),
847 block->height(), mWidth, mHeight, (int)buffer->user_private_data);
848
ming.zhouac19c3d2019-10-11 11:14:07 +0800849 uint8_t *dstY = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_Y]);
850 uint8_t *dstU = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_U]);
851 uint8_t *dstV = const_cast<uint8_t *>(wView.data()[C2PlanarLayout::PLANE_V]);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700852 size_t srcYStride = buffer->stride[0];
853 size_t srcUStride = buffer->stride[1];
854 size_t srcVStride = buffer->stride[2];
855
ming.zhouac19c3d2019-10-11 11:14:07 +0800856 C2PlanarLayout layout = wView.layout();
857 size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
858 size_t dstUVStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
859
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700860 if (buffer->bitdepth == 10) {
861 const uint16_t *srcY = (const uint16_t *)buffer->plane[0];
862 const uint16_t *srcU = (const uint16_t *)buffer->plane[1];
863 const uint16_t *srcV = (const uint16_t *)buffer->plane[2];
864
865 if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
Lajos Molnar45109a32022-06-03 09:41:48 -0700866 convertYUV420Planar16ToY410OrRGBA1010102(
867 (uint32_t *)dstY, srcY, srcU, srcV, srcYStride / 2,
868 srcUStride / 2, srcVStride / 2,
869 dstYStride / sizeof(uint32_t), mWidth, mHeight,
870 std::static_pointer_cast<const C2ColorAspectsStruct>(codedColorAspects));
Harish Mahendrakar1b1aef22021-12-30 19:12:51 -0800871 } else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
872 convertYUV420Planar16ToP010((uint16_t *)dstY, (uint16_t *)dstU, srcY, srcU, srcV,
873 srcYStride / 2, srcUStride / 2, srcVStride / 2, dstYStride / 2,
874 dstUVStride / 2, mWidth, mHeight, isMonochrome);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700875 } else {
Harish Mahendrakar1b1aef22021-12-30 19:12:51 -0800876 convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
877 srcUStride / 2, srcVStride / 2, dstYStride, dstUVStride, mWidth,
878 mHeight, isMonochrome);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700879 }
880 } else {
881 const uint8_t *srcY = (const uint8_t *)buffer->plane[0];
882 const uint8_t *srcU = (const uint8_t *)buffer->plane[1];
883 const uint8_t *srcV = (const uint8_t *)buffer->plane[2];
Harish Mahendrakar1b1aef22021-12-30 19:12:51 -0800884 convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
885 srcVStride, dstYStride, dstUVStride, mWidth, mHeight, isMonochrome);
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700886 }
887 finishWork(buffer->user_private_data, work, std::move(block));
888 block = nullptr;
889 return true;
890}
891
892c2_status_t C2SoftGav1Dec::drainInternal(
893 uint32_t drainMode, const std::shared_ptr<C2BlockPool> &pool,
894 const std::unique_ptr<C2Work> &work) {
895 if (drainMode == NO_DRAIN) {
896 ALOGW("drain with NO_DRAIN: no-op");
897 return C2_OK;
898 }
899 if (drainMode == DRAIN_CHAIN) {
900 ALOGW("DRAIN_CHAIN not supported");
901 return C2_OMITTED;
902 }
903
James Zernb7aee6e2020-06-26 13:49:53 -0700904 const Libgav1StatusCode status = mCodecCtx->SignalEOS();
Vignesh Venkatasubramanian0f3e7422019-06-17 16:21:36 -0700905 if (status != kLibgav1StatusOk) {
906 ALOGE("Failed to flush av1 decoder. status: %d.", status);
907 return C2_CORRUPTED;
908 }
909
910 while (outputBuffer(pool, work)) {
911 }
912
913 if (drainMode == DRAIN_COMPONENT_WITH_EOS && work &&
914 work->workletsProcessed == 0u) {
915 fillEmptyWork(work);
916 }
917
918 return C2_OK;
919}
920
921c2_status_t C2SoftGav1Dec::drain(uint32_t drainMode,
922 const std::shared_ptr<C2BlockPool> &pool) {
923 return drainInternal(drainMode, pool, nullptr);
924}
925
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700926class C2SoftGav1Factory : public C2ComponentFactory {
927 public:
928 C2SoftGav1Factory()
929 : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
930 GetCodec2PlatformComponentStore()->getParamReflector())) {}
931
932 virtual c2_status_t createComponent(
933 c2_node_id_t id, std::shared_ptr<C2Component> *const component,
934 std::function<void(C2Component *)> deleter) override {
935 *component = std::shared_ptr<C2Component>(
936 new C2SoftGav1Dec(COMPONENT_NAME, id,
937 std::make_shared<C2SoftGav1Dec::IntfImpl>(mHelper)),
938 deleter);
939 return C2_OK;
940 }
941
942 virtual c2_status_t createInterface(
943 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *const interface,
944 std::function<void(C2ComponentInterface *)> deleter) override {
945 *interface = std::shared_ptr<C2ComponentInterface>(
946 new SimpleInterface<C2SoftGav1Dec::IntfImpl>(
947 COMPONENT_NAME, id,
948 std::make_shared<C2SoftGav1Dec::IntfImpl>(mHelper)),
949 deleter);
950 return C2_OK;
951 }
952
953 virtual ~C2SoftGav1Factory() override = default;
954
955 private:
956 std::shared_ptr<C2ReflectorHelper> mHelper;
957};
958
959} // namespace android
960
Cindy Zhouf6c0c3c2020-12-02 10:53:40 -0800961__attribute__((cfi_canonical_jump_table))
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700962extern "C" ::C2ComponentFactory *CreateCodec2Factory() {
963 ALOGV("in %s", __func__);
964 return new ::android::C2SoftGav1Factory();
965}
966
Cindy Zhouf6c0c3c2020-12-02 10:53:40 -0800967__attribute__((cfi_canonical_jump_table))
Vignesh Venkatasubramanianb6d383d2019-06-10 15:11:58 -0700968extern "C" void DestroyCodec2Factory(::C2ComponentFactory *factory) {
969 ALOGV("in %s", __func__);
970 delete factory;
971}