xref: /aosp_15_r20/frameworks/av/media/codec2/components/aom/C2SoftAomDec.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "C2SoftAomDec"
19 #include <log/log.h>
20 
21 #include <media/stagefright/foundation/AUtils.h>
22 #include <media/stagefright/foundation/MediaDefs.h>
23 
24 #include <C2Debug.h>
25 #include <C2PlatformSupport.h>
26 #include <SimpleC2Interface.h>
27 
28 #include "C2SoftAomDec.h"
29 
30 namespace android {
31 
32 constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
33 
34 // codecname set and passed in as a compile flag from Android.bp
35 constexpr char COMPONENT_NAME[] = CODECNAME;
36 
37 class C2SoftAomDec::IntfImpl : public SimpleInterface<void>::BaseParams {
38   public:
IntfImpl(const std::shared_ptr<C2ReflectorHelper> & helper)39     explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper)
40         : SimpleInterface<void>::BaseParams(
41               helper, COMPONENT_NAME, C2Component::KIND_DECODER,
42               C2Component::DOMAIN_VIDEO, MEDIA_MIMETYPE_VIDEO_AV1) {
43         noPrivateBuffers();  // TODO: account for our buffers here
44         noInputReferences();
45         noOutputReferences();
46         noInputLatency();
47         noTimeStretch();
48 
49         addParameter(DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
50                          .withConstValue(new C2ComponentAttributesSetting(
51                              C2Component::ATTRIB_IS_TEMPORAL))
52                          .build());
53 
54         addParameter(
55             DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
56                 .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
57                 .withFields({
58                     C2F(mSize, width).inRange(2, 2048, 2),
59                     C2F(mSize, height).inRange(2, 2048, 2),
60                 })
61                 .withSetter(SizeSetter)
62                 .build());
63 
64         addParameter(
65                 DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
66                 .withDefault(new C2StreamProfileLevelInfo::input(0u,
67                         C2Config::PROFILE_AV1_0, C2Config::LEVEL_AV1_2_1))
68                 .withFields({
69                     C2F(mProfileLevel, profile).oneOf({
70                             C2Config::PROFILE_AV1_0,
71                             C2Config::PROFILE_AV1_1}),
72                     C2F(mProfileLevel, level).oneOf({
73                             C2Config::LEVEL_AV1_2,
74                             C2Config::LEVEL_AV1_2_1,
75                             C2Config::LEVEL_AV1_2_2,
76                             C2Config::LEVEL_AV1_3,
77                             C2Config::LEVEL_AV1_3_1,
78                             C2Config::LEVEL_AV1_3_2,
79                     })
80                 })
81                 .withSetter(ProfileLevelSetter, mSize)
82                 .build());
83 
84         mHdr10PlusInfoInput = C2StreamHdr10PlusInfo::input::AllocShared(0);
85         addParameter(
86                 DefineParam(mHdr10PlusInfoInput, C2_PARAMKEY_INPUT_HDR10_PLUS_INFO)
87                 .withDefault(mHdr10PlusInfoInput)
88                 .withFields({
89                     C2F(mHdr10PlusInfoInput, m.value).any(),
90                 })
91                 .withSetter(Hdr10PlusInfoInputSetter)
92                 .build());
93 
94         mHdr10PlusInfoOutput = C2StreamHdr10PlusInfo::output::AllocShared(0);
95         addParameter(
96                 DefineParam(mHdr10PlusInfoOutput, C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO)
97                 .withDefault(mHdr10PlusInfoOutput)
98                 .withFields({
99                     C2F(mHdr10PlusInfoOutput, m.value).any(),
100                 })
101                 .withSetter(Hdr10PlusInfoOutputSetter)
102                 .build());
103 
104         addParameter(DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
105                          .withDefault(new C2StreamMaxPictureSizeTuning::output(
106                              0u, 320, 240))
107                          .withFields({
108                              C2F(mSize, width).inRange(2, 2048, 2),
109                              C2F(mSize, height).inRange(2, 2048, 2),
110                          })
111                          .withSetter(MaxPictureSizeSetter, mSize)
112                          .build());
113 
114         addParameter(
115             DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
116                 .withDefault(
117                     new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
118                 .withFields({
119                     C2F(mMaxInputSize, value).any(),
120                 })
121                 .calculatedAs(MaxInputSizeSetter, mMaxSize)
122                 .build());
123 
124         C2ChromaOffsetStruct locations[1] = {
125             C2ChromaOffsetStruct::ITU_YUV_420_0()};
126         std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
127             C2StreamColorInfo::output::AllocShared(1u, 0u, 8u /* bitDepth */,
128                                                    C2Color::YUV_420);
129         memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
130 
131         defaultColorInfo = C2StreamColorInfo::output::AllocShared(
132             {C2ChromaOffsetStruct::ITU_YUV_420_0()}, 0u, 8u /* bitDepth */,
133             C2Color::YUV_420);
134         helper->addStructDescriptors<C2ChromaOffsetStruct>();
135 
136         addParameter(DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
137                          .withConstValue(defaultColorInfo)
138                          .build());
139 
140         addParameter(
141                 DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
142                 .withDefault(new C2StreamColorAspectsTuning::output(
143                         0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
144                         C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
145                 .withFields({
146                     C2F(mDefaultColorAspects, range).inRange(
147                                 C2Color::RANGE_UNSPECIFIED,     C2Color::RANGE_OTHER),
148                     C2F(mDefaultColorAspects, primaries).inRange(
149                                 C2Color::PRIMARIES_UNSPECIFIED, C2Color::PRIMARIES_OTHER),
150                     C2F(mDefaultColorAspects, transfer).inRange(
151                                 C2Color::TRANSFER_UNSPECIFIED,  C2Color::TRANSFER_OTHER),
152                     C2F(mDefaultColorAspects, matrix).inRange(
153                                 C2Color::MATRIX_UNSPECIFIED,    C2Color::MATRIX_OTHER)
154                 })
155                 .withSetter(DefaultColorAspectsSetter)
156                 .build());
157 
158         // TODO: support more formats?
159         addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
160                          .withConstValue(new C2StreamPixelFormatInfo::output(
161                              0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
162                          .build());
163     }
164 
SizeSetter(bool mayBlock,const C2P<C2StreamPictureSizeInfo::output> & oldMe,C2P<C2StreamPictureSizeInfo::output> & me)165     static C2R SizeSetter(bool mayBlock,
166                           const C2P<C2StreamPictureSizeInfo::output>& oldMe,
167                           C2P<C2StreamPictureSizeInfo::output>& me) {
168         (void)mayBlock;
169         C2R res = C2R::Ok();
170         if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
171             res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
172             me.set().width = oldMe.v.width;
173         }
174         if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
175             res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
176             me.set().height = oldMe.v.height;
177         }
178         return res;
179     }
180 
MaxPictureSizeSetter(bool mayBlock,C2P<C2StreamMaxPictureSizeTuning::output> & me,const C2P<C2StreamPictureSizeInfo::output> & size)181     static C2R MaxPictureSizeSetter(
182         bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output>& me,
183         const C2P<C2StreamPictureSizeInfo::output>& size) {
184         (void)mayBlock;
185         // TODO: get max width/height from the size's field helpers vs.
186         // hardcoding
187         me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4096u);
188         me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4096u);
189         return C2R::Ok();
190     }
191 
MaxInputSizeSetter(bool mayBlock,C2P<C2StreamMaxBufferSizeInfo::input> & me,const C2P<C2StreamMaxPictureSizeTuning::output> & maxSize)192     static C2R MaxInputSizeSetter(
193         bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input>& me,
194         const C2P<C2StreamMaxPictureSizeTuning::output>& maxSize) {
195         (void)mayBlock;
196         // assume compression ratio of 2
197         me.set().value = c2_max((((maxSize.v.width + 63) / 64)
198                 * ((maxSize.v.height + 63) / 64) * 3072), kMinInputBufferSize);
199         return C2R::Ok();
200     }
DefaultColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsTuning::output> & me)201     static C2R DefaultColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsTuning::output> &me) {
202         (void)mayBlock;
203         if (me.v.range > C2Color::RANGE_OTHER) {
204             me.set().range = C2Color::RANGE_OTHER;
205         }
206         if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
207             me.set().primaries = C2Color::PRIMARIES_OTHER;
208         }
209         if (me.v.transfer > C2Color::TRANSFER_OTHER) {
210             me.set().transfer = C2Color::TRANSFER_OTHER;
211         }
212         if (me.v.matrix > C2Color::MATRIX_OTHER) {
213             me.set().matrix = C2Color::MATRIX_OTHER;
214         }
215         return C2R::Ok();
216     }
217 
ProfileLevelSetter(bool mayBlock,C2P<C2StreamProfileLevelInfo::input> & me,const C2P<C2StreamPictureSizeInfo::output> & size)218     static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
219                                   const C2P<C2StreamPictureSizeInfo::output> &size) {
220         (void)mayBlock;
221         (void)size;
222         (void)me;  // TODO: validate
223         return C2R::Ok();
224     }
getDefaultColorAspects_l()225     std::shared_ptr<C2StreamColorAspectsTuning::output> getDefaultColorAspects_l() {
226         return mDefaultColorAspects;
227     }
228 
Hdr10PlusInfoInputSetter(bool mayBlock,C2P<C2StreamHdr10PlusInfo::input> & me)229     static C2R Hdr10PlusInfoInputSetter(bool mayBlock, C2P<C2StreamHdr10PlusInfo::input> &me) {
230         (void)mayBlock;
231         (void)me;  // TODO: validate
232         return C2R::Ok();
233     }
234 
Hdr10PlusInfoOutputSetter(bool mayBlock,C2P<C2StreamHdr10PlusInfo::output> & me)235     static C2R Hdr10PlusInfoOutputSetter(bool mayBlock, C2P<C2StreamHdr10PlusInfo::output> &me) {
236         (void)mayBlock;
237         (void)me;  // TODO: validate
238         return C2R::Ok();
239     }
240 
241   private:
242     std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
243     std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
244     std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize;
245     std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize;
246     std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
247     std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
248     std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
249     std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput;
250     std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput;
251 };
252 
C2SoftAomDec(const char * name,c2_node_id_t id,const std::shared_ptr<IntfImpl> & intfImpl)253 C2SoftAomDec::C2SoftAomDec(const char* name, c2_node_id_t id,
254                            const std::shared_ptr<IntfImpl>& intfImpl)
255     : SimpleC2Component(
256           std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
257       mIntf(intfImpl),
258       mCodecCtx(nullptr){
259 
260     GENERATE_FILE_NAMES();
261     CREATE_DUMP_FILE(mInFile);
262     CREATE_DUMP_FILE(mOutFile);
263 
264     mTimeStart = mTimeEnd = systemTime();
265 }
266 
~C2SoftAomDec()267 C2SoftAomDec::~C2SoftAomDec() {
268     onRelease();
269 }
270 
onInit()271 c2_status_t C2SoftAomDec::onInit() {
272     status_t err = initDecoder();
273     return err == OK ? C2_OK : C2_CORRUPTED;
274 }
275 
onStop()276 c2_status_t C2SoftAomDec::onStop() {
277     mSignalledError = false;
278     mSignalledOutputEos = false;
279     return C2_OK;
280 }
281 
onReset()282 void C2SoftAomDec::onReset() {
283     (void)onStop();
284     c2_status_t err = onFlush_sm();
285     if (err != C2_OK) {
286         ALOGW("Failed to flush decoder. Try to hard reset decoder.");
287         destroyDecoder();
288         (void)initDecoder();
289     }
290 }
291 
onRelease()292 void C2SoftAomDec::onRelease() {
293     destroyDecoder();
294 }
295 
onFlush_sm()296 c2_status_t C2SoftAomDec::onFlush_sm() {
297     if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
298         ALOGE("Failed to flush av1 decoder.");
299         return C2_CORRUPTED;
300     }
301 
302     aom_codec_iter_t iter = nullptr;
303     while (aom_codec_get_frame(mCodecCtx, &iter)) {
304     }
305 
306     mSignalledError = false;
307     mSignalledOutputEos = false;
308 
309     return C2_OK;
310 }
311 
GetCPUCoreCount()312 static int GetCPUCoreCount() {
313     int cpuCoreCount = 1;
314 #if defined(_SC_NPROCESSORS_ONLN)
315     cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
316 #else
317     // _SC_NPROC_ONLN must be defined...
318     cpuCoreCount = sysconf(_SC_NPROC_ONLN);
319 #endif
320     CHECK(cpuCoreCount >= 1);
321     ALOGV("Number of CPU cores: %d", cpuCoreCount);
322     return cpuCoreCount;
323 }
324 
initDecoder()325 status_t C2SoftAomDec::initDecoder() {
326     mSignalledError = false;
327     mSignalledOutputEos = false;
328     if (!mCodecCtx) {
329         mCodecCtx = new aom_codec_ctx_t;
330     }
331 
332     if (!mCodecCtx) {
333         ALOGE("mCodecCtx is null");
334         return NO_MEMORY;
335     }
336 
337     aom_codec_dec_cfg_t cfg;
338     memset(&cfg, 0, sizeof(aom_codec_dec_cfg_t));
339     cfg.threads = GetCPUCoreCount();
340     cfg.allow_lowbitdepth = 1;
341 
342     aom_codec_flags_t flags;
343     memset(&flags, 0, sizeof(aom_codec_flags_t));
344 
345     ALOGV("Using libaom AV1 software decoder.");
346     aom_codec_err_t err;
347     if ((err = aom_codec_dec_init(mCodecCtx, aom_codec_av1_dx(), &cfg, 0))) {
348         ALOGE("av1 decoder failed to initialize. (%d)", err);
349         return UNKNOWN_ERROR;
350     }
351 
352     return OK;
353 }
354 
destroyDecoder()355 status_t C2SoftAomDec::destroyDecoder() {
356     if (mCodecCtx) {
357         aom_codec_destroy(mCodecCtx);
358         delete mCodecCtx;
359         mCodecCtx = nullptr;
360     }
361     return OK;
362 }
363 
fillEmptyWork(const std::unique_ptr<C2Work> & work)364 void fillEmptyWork(const std::unique_ptr<C2Work>& work) {
365     uint32_t flags = 0;
366     if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
367         flags |= C2FrameData::FLAG_END_OF_STREAM;
368         ALOGV("signalling eos");
369     }
370     work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
371     work->worklets.front()->output.buffers.clear();
372     work->worklets.front()->output.ordinal = work->input.ordinal;
373     work->workletsProcessed = 1u;
374 }
375 
finishWork(uint64_t index,const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2GraphicBlock> & block)376 void C2SoftAomDec::finishWork(uint64_t index,
377                               const std::unique_ptr<C2Work>& work,
378                               const std::shared_ptr<C2GraphicBlock>& block) {
379     std::shared_ptr<C2Buffer> buffer =
380         createGraphicBuffer(block, C2Rect(mWidth, mHeight));
381     auto fillWork = [buffer, index, intf = this->mIntf](
382             const std::unique_ptr<C2Work>& work) {
383         uint32_t flags = 0;
384         if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
385             (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
386             flags |= C2FrameData::FLAG_END_OF_STREAM;
387             ALOGV("signalling eos");
388         }
389         work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
390         work->worklets.front()->output.buffers.clear();
391         work->worklets.front()->output.buffers.push_back(buffer);
392         work->worklets.front()->output.ordinal = work->input.ordinal;
393         work->workletsProcessed = 1u;
394 
395         for (const std::unique_ptr<C2Param> &param: work->input.configUpdate) {
396             if (param) {
397                 C2StreamHdr10PlusInfo::input *hdr10PlusInfo =
398                         C2StreamHdr10PlusInfo::input::From(param.get());
399 
400                 if (hdr10PlusInfo != nullptr) {
401                     std::vector<std::unique_ptr<C2SettingResult>> failures;
402                     std::unique_ptr<C2Param> outParam = C2Param::CopyAsStream(
403                             *param.get(), true /*output*/, param->stream());
404                     c2_status_t err = intf->config(
405                             { outParam.get() }, C2_MAY_BLOCK, &failures);
406                     if (err == C2_OK) {
407                         work->worklets.front()->output.configUpdate.push_back(
408                                 C2Param::Copy(*outParam.get()));
409                     } else {
410                         ALOGE("finishWork: Config update size failed");
411                     }
412                     break;
413                 }
414             }
415         }
416     };
417     if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
418         fillWork(work);
419     } else {
420         finish(index, fillWork);
421     }
422 }
423 
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)424 void C2SoftAomDec::process(const std::unique_ptr<C2Work>& work,
425                            const std::shared_ptr<C2BlockPool>& pool) {
426     work->result = C2_OK;
427     work->workletsProcessed = 0u;
428     work->worklets.front()->output.configUpdate.clear();
429     work->worklets.front()->output.flags = work->input.flags;
430     if (mSignalledError || mSignalledOutputEos) {
431         work->result = C2_BAD_VALUE;
432         return;
433     }
434 
435     size_t inOffset = 0u;
436     size_t inSize = 0u;
437     C2ReadView rView = mDummyReadView;
438     if (!work->input.buffers.empty()) {
439         rView =
440             work->input.buffers[0]->data().linearBlocks().front().map().get();
441         inSize = rView.capacity();
442         if (inSize && rView.error()) {
443             ALOGE("read view map failed %d", rView.error());
444             work->result = C2_CORRUPTED;
445             return;
446         }
447     }
448 
449     bool codecConfig =
450         ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0);
451     bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
452 
453     ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
454           inSize, (int)work->input.ordinal.timestamp.peeku(),
455           (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
456 
457     if (codecConfig) {
458         fillEmptyWork(work);
459         return;
460     }
461 
462     int64_t frameIndex = work->input.ordinal.frameIndex.peekll();
463     if (inSize) {
464         uint8_t* bitstream = const_cast<uint8_t*>(rView.data() + inOffset);
465 
466         DUMP_TO_FILE(mOutFile, bitstream, inSize);
467         mTimeStart = systemTime();
468         nsecs_t delay = mTimeStart - mTimeEnd;
469 
470         aom_codec_err_t err =
471             aom_codec_decode(mCodecCtx, bitstream, inSize, &frameIndex);
472 
473         mTimeEnd = systemTime();
474         nsecs_t decodeTime = mTimeEnd - mTimeStart;
475         ALOGV("decodeTime=%4" PRId64 " delay=%4" PRId64 "\n", decodeTime, delay);
476 
477         if (err != AOM_CODEC_OK) {
478             ALOGE("av1 decoder failed to decode frame err: %d", err);
479             work->result = C2_CORRUPTED;
480             work->workletsProcessed = 1u;
481             mSignalledError = true;
482             return;
483         }
484 
485     } else {
486         if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
487             ALOGE("Failed to flush av1 decoder.");
488             work->result = C2_CORRUPTED;
489             work->workletsProcessed = 1u;
490             mSignalledError = true;
491             return;
492         }
493     }
494 
495     (void)outputBuffer(pool, work);
496 
497     if (eos) {
498         drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
499         mSignalledOutputEos = true;
500     } else if (!inSize) {
501         fillEmptyWork(work);
502     }
503 }
504 
outputBuffer(const std::shared_ptr<C2BlockPool> & pool,const std::unique_ptr<C2Work> & work)505 bool C2SoftAomDec::outputBuffer(
506         const std::shared_ptr<C2BlockPool> &pool,
507         const std::unique_ptr<C2Work> &work)
508 {
509     if (!(work && pool)) return false;
510 
511     aom_codec_iter_t iter = nullptr;
512     aom_image_t* img = aom_codec_get_frame(mCodecCtx, &iter);
513 
514     if (!img) return false;
515 
516     if (img->d_w != mWidth || img->d_h != mHeight) {
517         mWidth = img->d_w;
518         mHeight = img->d_h;
519 
520         C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
521         std::vector<std::unique_ptr<C2SettingResult>> failures;
522         c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
523         if (err == C2_OK) {
524             work->worklets.front()->output.configUpdate.push_back(
525                 C2Param::Copy(size));
526         } else {
527             ALOGE("Config update size failed");
528             mSignalledError = true;
529             work->result = C2_CORRUPTED;
530             work->workletsProcessed = 1u;
531             return false;
532         }
533     }
534 
535     CHECK(img->fmt == AOM_IMG_FMT_I420 || img->fmt == AOM_IMG_FMT_I42016);
536 
537     std::shared_ptr<C2GraphicBlock> block;
538     uint32_t format = HAL_PIXEL_FORMAT_YV12;
539     std::shared_ptr<C2StreamColorAspectsTuning::output> defaultColorAspects;
540     if (img->fmt == AOM_IMG_FMT_I42016) {
541         IntfImpl::Lock lock = mIntf->lock();
542         defaultColorAspects = mIntf->getDefaultColorAspects_l();
543 
544         if (defaultColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
545             defaultColorAspects->matrix == C2Color::MATRIX_BT2020 &&
546             defaultColorAspects->transfer == C2Color::TRANSFER_ST2084) {
547             format = HAL_PIXEL_FORMAT_RGBA_1010102;
548         }
549     }
550     C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
551 
552     c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16), mHeight,
553                                               format, usage, &block);
554 
555     if (err != C2_OK) {
556         ALOGE("fetchGraphicBlock for Output failed with status %d", err);
557         work->result = err;
558         return false;
559     }
560 
561     C2GraphicView wView = block->map().get();
562 
563     if (wView.error()) {
564         ALOGE("graphic view map failed %d", wView.error());
565         work->result = C2_CORRUPTED;
566         return false;
567     }
568 
569     ALOGV("provided (%dx%d) required (%dx%d), out frameindex %d",
570           block->width(), block->height(), mWidth, mHeight,
571           (int)*(int64_t*)img->user_priv);
572 
573     uint8_t* dstY = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_Y]);
574     uint8_t* dstU = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_U]);
575     uint8_t* dstV = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_V]);
576     size_t srcYStride = img->stride[AOM_PLANE_Y];
577     size_t srcUStride = img->stride[AOM_PLANE_U];
578     size_t srcVStride = img->stride[AOM_PLANE_V];
579     C2PlanarLayout layout = wView.layout();
580     size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
581     size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
582     size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
583 
584     if (img->fmt == AOM_IMG_FMT_I42016) {
585         const uint16_t *srcY = (const uint16_t *)img->planes[AOM_PLANE_Y];
586         const uint16_t *srcU = (const uint16_t *)img->planes[AOM_PLANE_U];
587         const uint16_t *srcV = (const uint16_t *)img->planes[AOM_PLANE_V];
588 
589         if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
590             convertYUV420Planar16ToY410OrRGBA1010102(
591                     (uint32_t *)dstY, srcY, srcU, srcV, srcYStride / 2, srcUStride / 2,
592                     srcVStride / 2, dstYStride / sizeof(uint32_t), mWidth, mHeight,
593                     std::static_pointer_cast<const C2ColorAspectsStruct>(defaultColorAspects));
594         } else {
595             convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
596                                         srcUStride / 2, srcVStride / 2, dstYStride, dstUStride,
597                                         mWidth, mHeight);
598         }
599     } else {
600         const uint8_t *srcY = (const uint8_t *)img->planes[AOM_PLANE_Y];
601         const uint8_t *srcU = (const uint8_t *)img->planes[AOM_PLANE_U];
602         const uint8_t *srcV = (const uint8_t *)img->planes[AOM_PLANE_V];
603         convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
604                                    srcVStride, dstYStride, dstUStride, dstVStride, mWidth, mHeight);
605     }
606     finishWork(*(int64_t*)img->user_priv, work, std::move(block));
607     block = nullptr;
608     return true;
609 }
610 
drainInternal(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool,const std::unique_ptr<C2Work> & work)611 c2_status_t C2SoftAomDec::drainInternal(
612     uint32_t drainMode, const std::shared_ptr<C2BlockPool>& pool,
613     const std::unique_ptr<C2Work>& work) {
614     if (drainMode == NO_DRAIN) {
615         ALOGW("drain with NO_DRAIN: no-op");
616         return C2_OK;
617     }
618     if (drainMode == DRAIN_CHAIN) {
619         ALOGW("DRAIN_CHAIN not supported");
620         return C2_OMITTED;
621     }
622 
623     if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
624         ALOGE("Failed to flush av1 decoder.");
625         return C2_CORRUPTED;
626     }
627 
628     while ((outputBuffer(pool, work))) {
629     }
630 
631     if (drainMode == DRAIN_COMPONENT_WITH_EOS && work &&
632         work->workletsProcessed == 0u) {
633         fillEmptyWork(work);
634     }
635 
636     return C2_OK;
637 }
638 
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)639 c2_status_t C2SoftAomDec::drain(uint32_t drainMode,
640                                 const std::shared_ptr<C2BlockPool>& pool) {
641     return drainInternal(drainMode, pool, nullptr);
642 }
643 
644 class C2SoftAomFactory : public C2ComponentFactory {
645    public:
C2SoftAomFactory()646     C2SoftAomFactory()
647         : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
648               GetCodec2PlatformComponentStore()->getParamReflector())) {}
649 
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)650     virtual c2_status_t createComponent(
651         c2_node_id_t id, std::shared_ptr<C2Component>* const component,
652         std::function<void(C2Component*)> deleter) override {
653         *component = std::shared_ptr<C2Component>(
654             new C2SoftAomDec(COMPONENT_NAME, id,
655                              std::make_shared<C2SoftAomDec::IntfImpl>(mHelper)),
656             deleter);
657         return C2_OK;
658     }
659 
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)660     virtual c2_status_t createInterface(
661         c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
662         std::function<void(C2ComponentInterface*)> deleter) override {
663         *interface = std::shared_ptr<C2ComponentInterface>(
664             new SimpleInterface<C2SoftAomDec::IntfImpl>(
665                 COMPONENT_NAME, id,
666                 std::make_shared<C2SoftAomDec::IntfImpl>(mHelper)),
667             deleter);
668         return C2_OK;
669     }
670 
671     virtual ~C2SoftAomFactory() override = default;
672 
673    private:
674     std::shared_ptr<C2ReflectorHelper> mHelper;
675 };
676 
677 }  // namespace android
678 
679 __attribute__((cfi_canonical_jump_table))
CreateCodec2Factory()680 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
681     ALOGV("in %s", __func__);
682     return new ::android::C2SoftAomFactory();
683 }
684 
685 __attribute__((cfi_canonical_jump_table))
DestroyCodec2Factory(::C2ComponentFactory * factory)686 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
687     ALOGV("in %s", __func__);
688     delete factory;
689 }
690