• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(const char * name,c2_node_id_t id,const std::shared_ptr<C2ReflectorHelper> & helper)267 C2SoftAomDec::C2SoftAomDec(const char* name, c2_node_id_t id,
268                            const std::shared_ptr<C2ReflectorHelper>& helper)
269     : C2SoftAomDec(name, id, std::make_shared<IntfImpl>(helper)) {
270 }
271 
~C2SoftAomDec()272 C2SoftAomDec::~C2SoftAomDec() {
273     onRelease();
274 }
275 
onInit()276 c2_status_t C2SoftAomDec::onInit() {
277     status_t err = initDecoder();
278     return err == OK ? C2_OK : C2_CORRUPTED;
279 }
280 
onStop()281 c2_status_t C2SoftAomDec::onStop() {
282     mSignalledError = false;
283     mSignalledOutputEos = false;
284     return C2_OK;
285 }
286 
onReset()287 void C2SoftAomDec::onReset() {
288     (void)onStop();
289     c2_status_t err = onFlush_sm();
290     if (err != C2_OK) {
291         ALOGW("Failed to flush decoder. Try to hard reset decoder.");
292         destroyDecoder();
293         (void)initDecoder();
294     }
295 }
296 
onRelease()297 void C2SoftAomDec::onRelease() {
298     destroyDecoder();
299 }
300 
onFlush_sm()301 c2_status_t C2SoftAomDec::onFlush_sm() {
302     if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
303         ALOGE("Failed to flush av1 decoder.");
304         return C2_CORRUPTED;
305     }
306 
307     aom_codec_iter_t iter = nullptr;
308     while (aom_codec_get_frame(mCodecCtx, &iter)) {
309     }
310 
311     mSignalledError = false;
312     mSignalledOutputEos = false;
313 
314     return C2_OK;
315 }
316 
GetCPUCoreCount()317 static int GetCPUCoreCount() {
318     int cpuCoreCount = 1;
319 #if defined(_SC_NPROCESSORS_ONLN)
320     cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
321 #else
322     // _SC_NPROC_ONLN must be defined...
323     cpuCoreCount = sysconf(_SC_NPROC_ONLN);
324 #endif
325     CHECK(cpuCoreCount >= 1);
326     ALOGV("Number of CPU cores: %d", cpuCoreCount);
327     return cpuCoreCount;
328 }
329 
initDecoder()330 status_t C2SoftAomDec::initDecoder() {
331     mSignalledError = false;
332     mSignalledOutputEos = false;
333     if (!mCodecCtx) {
334         mCodecCtx = new aom_codec_ctx_t;
335     }
336 
337     if (!mCodecCtx) {
338         ALOGE("mCodecCtx is null");
339         return NO_MEMORY;
340     }
341 
342     aom_codec_dec_cfg_t cfg;
343     memset(&cfg, 0, sizeof(aom_codec_dec_cfg_t));
344     cfg.threads = GetCPUCoreCount();
345     cfg.allow_lowbitdepth = 1;
346 
347     aom_codec_flags_t flags;
348     memset(&flags, 0, sizeof(aom_codec_flags_t));
349 
350     ALOGV("Using libaom AV1 software decoder.");
351     aom_codec_err_t err;
352     if ((err = aom_codec_dec_init(mCodecCtx, aom_codec_av1_dx(), &cfg, 0))) {
353         ALOGE("av1 decoder failed to initialize. (%d)", err);
354         return UNKNOWN_ERROR;
355     }
356 
357     return OK;
358 }
359 
destroyDecoder()360 status_t C2SoftAomDec::destroyDecoder() {
361     if (mCodecCtx) {
362         aom_codec_destroy(mCodecCtx);
363         delete mCodecCtx;
364         mCodecCtx = nullptr;
365     }
366     return OK;
367 }
368 
fillEmptyWork(const std::unique_ptr<C2Work> & work)369 void fillEmptyWork(const std::unique_ptr<C2Work>& work) {
370     uint32_t flags = 0;
371     if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
372         flags |= C2FrameData::FLAG_END_OF_STREAM;
373         ALOGV("signalling eos");
374     }
375     work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
376     work->worklets.front()->output.buffers.clear();
377     work->worklets.front()->output.ordinal = work->input.ordinal;
378     work->workletsProcessed = 1u;
379 }
380 
finishWork(uint64_t index,const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2GraphicBlock> & block)381 void C2SoftAomDec::finishWork(uint64_t index,
382                               const std::unique_ptr<C2Work>& work,
383                               const std::shared_ptr<C2GraphicBlock>& block) {
384     std::shared_ptr<C2Buffer> buffer =
385         createGraphicBuffer(block, C2Rect(mWidth, mHeight));
386     auto fillWork = [buffer, index, intf = this->mIntf](
387             const std::unique_ptr<C2Work>& work) {
388         uint32_t flags = 0;
389         if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
390             (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
391             flags |= C2FrameData::FLAG_END_OF_STREAM;
392             ALOGV("signalling eos");
393         }
394         work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
395         work->worklets.front()->output.buffers.clear();
396         work->worklets.front()->output.buffers.push_back(buffer);
397         work->worklets.front()->output.ordinal = work->input.ordinal;
398         work->workletsProcessed = 1u;
399 
400         for (const std::unique_ptr<C2Param> &param: work->input.configUpdate) {
401             if (param) {
402                 C2StreamHdr10PlusInfo::input *hdr10PlusInfo =
403                         C2StreamHdr10PlusInfo::input::From(param.get());
404 
405                 if (hdr10PlusInfo != nullptr) {
406                     std::vector<std::unique_ptr<C2SettingResult>> failures;
407                     std::unique_ptr<C2Param> outParam = C2Param::CopyAsStream(
408                             *param.get(), true /*output*/, param->stream());
409                     c2_status_t err = intf->config(
410                             { outParam.get() }, C2_MAY_BLOCK, &failures);
411                     if (err == C2_OK) {
412                         work->worklets.front()->output.configUpdate.push_back(
413                                 C2Param::Copy(*outParam.get()));
414                     } else {
415                         ALOGE("finishWork: Config update size failed");
416                     }
417                     break;
418                 }
419             }
420         }
421     };
422     if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
423         fillWork(work);
424     } else {
425         finish(index, fillWork);
426     }
427 }
428 
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)429 void C2SoftAomDec::process(const std::unique_ptr<C2Work>& work,
430                            const std::shared_ptr<C2BlockPool>& pool) {
431     work->result = C2_OK;
432     work->workletsProcessed = 0u;
433     work->worklets.front()->output.configUpdate.clear();
434     work->worklets.front()->output.flags = work->input.flags;
435     if (mSignalledError || mSignalledOutputEos) {
436         work->result = C2_BAD_VALUE;
437         return;
438     }
439 
440     size_t inOffset = 0u;
441     size_t inSize = 0u;
442     C2ReadView rView = mDummyReadView;
443     if (!work->input.buffers.empty()) {
444         rView =
445             work->input.buffers[0]->data().linearBlocks().front().map().get();
446         inSize = rView.capacity();
447         if (inSize && rView.error()) {
448             ALOGE("read view map failed %d", rView.error());
449             work->result = C2_CORRUPTED;
450             return;
451         }
452     }
453 
454     bool codecConfig =
455         ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0);
456     bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
457 
458     ALOGV("in buffer attr. size %zu timestamp %d frameindex %d, flags %x",
459           inSize, (int)work->input.ordinal.timestamp.peeku(),
460           (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
461 
462     if (codecConfig) {
463         fillEmptyWork(work);
464         return;
465     }
466 
467     int64_t frameIndex = work->input.ordinal.frameIndex.peekll();
468     if (inSize) {
469         uint8_t* bitstream = const_cast<uint8_t*>(rView.data() + inOffset);
470 
471         DUMP_TO_FILE(mOutFile, bitstream, inSize);
472         mTimeStart = systemTime();
473         nsecs_t delay = mTimeStart - mTimeEnd;
474 
475         aom_codec_err_t err =
476             aom_codec_decode(mCodecCtx, bitstream, inSize, &frameIndex);
477 
478         mTimeEnd = systemTime();
479         nsecs_t decodeTime = mTimeEnd - mTimeStart;
480         ALOGV("decodeTime=%4" PRId64 " delay=%4" PRId64 "\n", decodeTime, delay);
481 
482         if (err != AOM_CODEC_OK) {
483             ALOGE("av1 decoder failed to decode frame err: %d", err);
484             work->result = C2_CORRUPTED;
485             work->workletsProcessed = 1u;
486             mSignalledError = true;
487             return;
488         }
489 
490     } else {
491         if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
492             ALOGE("Failed to flush av1 decoder.");
493             work->result = C2_CORRUPTED;
494             work->workletsProcessed = 1u;
495             mSignalledError = true;
496             return;
497         }
498     }
499 
500     (void)outputBuffer(pool, work);
501 
502     if (eos) {
503         drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
504         mSignalledOutputEos = true;
505     } else if (!inSize) {
506         fillEmptyWork(work);
507     }
508 }
509 
outputBuffer(const std::shared_ptr<C2BlockPool> & pool,const std::unique_ptr<C2Work> & work)510 bool C2SoftAomDec::outputBuffer(
511         const std::shared_ptr<C2BlockPool> &pool,
512         const std::unique_ptr<C2Work> &work)
513 {
514     if (!(work && pool)) return false;
515 
516     aom_codec_iter_t iter = nullptr;
517     aom_image_t* img = aom_codec_get_frame(mCodecCtx, &iter);
518 
519     if (!img) return false;
520 
521     if (img->d_w != mWidth || img->d_h != mHeight) {
522         mWidth = img->d_w;
523         mHeight = img->d_h;
524 
525         C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
526         std::vector<std::unique_ptr<C2SettingResult>> failures;
527         c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
528         if (err == C2_OK) {
529             work->worklets.front()->output.configUpdate.push_back(
530                 C2Param::Copy(size));
531         } else {
532             ALOGE("Config update size failed");
533             mSignalledError = true;
534             work->result = C2_CORRUPTED;
535             work->workletsProcessed = 1u;
536             return false;
537         }
538     }
539 
540     CHECK(img->fmt == AOM_IMG_FMT_I420 || img->fmt == AOM_IMG_FMT_I42016);
541 
542     std::shared_ptr<C2GraphicBlock> block;
543     uint32_t format = HAL_PIXEL_FORMAT_YV12;
544     std::shared_ptr<C2StreamColorAspectsTuning::output> defaultColorAspects;
545     if (img->fmt == AOM_IMG_FMT_I42016) {
546         IntfImpl::Lock lock = mIntf->lock();
547         defaultColorAspects = mIntf->getDefaultColorAspects_l();
548 
549         if (defaultColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
550             defaultColorAspects->matrix == C2Color::MATRIX_BT2020 &&
551             defaultColorAspects->transfer == C2Color::TRANSFER_ST2084) {
552             format = HAL_PIXEL_FORMAT_RGBA_1010102;
553         }
554     }
555     C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
556 
557     c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16), mHeight,
558                                               format, usage, &block);
559 
560     if (err != C2_OK) {
561         ALOGE("fetchGraphicBlock for Output failed with status %d", err);
562         work->result = err;
563         return false;
564     }
565 
566     C2GraphicView wView = block->map().get();
567 
568     if (wView.error()) {
569         ALOGE("graphic view map failed %d", wView.error());
570         work->result = C2_CORRUPTED;
571         return false;
572     }
573 
574     ALOGV("provided (%dx%d) required (%dx%d), out frameindex %d",
575           block->width(), block->height(), mWidth, mHeight,
576           (int)*(int64_t*)img->user_priv);
577 
578     uint8_t* dstY = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_Y]);
579     uint8_t* dstU = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_U]);
580     uint8_t* dstV = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_V]);
581     size_t srcYStride = img->stride[AOM_PLANE_Y];
582     size_t srcUStride = img->stride[AOM_PLANE_U];
583     size_t srcVStride = img->stride[AOM_PLANE_V];
584     C2PlanarLayout layout = wView.layout();
585     size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
586     size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
587     size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
588 
589     if (img->fmt == AOM_IMG_FMT_I42016) {
590         const uint16_t *srcY = (const uint16_t *)img->planes[AOM_PLANE_Y];
591         const uint16_t *srcU = (const uint16_t *)img->planes[AOM_PLANE_U];
592         const uint16_t *srcV = (const uint16_t *)img->planes[AOM_PLANE_V];
593 
594         if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
595             convertYUV420Planar16ToY410OrRGBA1010102(
596                     (uint32_t *)dstY, srcY, srcU, srcV, srcYStride / 2, srcUStride / 2,
597                     srcVStride / 2, dstYStride / sizeof(uint32_t), mWidth, mHeight,
598                     std::static_pointer_cast<const C2ColorAspectsStruct>(defaultColorAspects));
599         } else {
600             convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride / 2,
601                                         srcUStride / 2, srcVStride / 2, dstYStride, dstUStride,
602                                         mWidth, mHeight);
603         }
604     } else {
605         const uint8_t *srcY = (const uint8_t *)img->planes[AOM_PLANE_Y];
606         const uint8_t *srcU = (const uint8_t *)img->planes[AOM_PLANE_U];
607         const uint8_t *srcV = (const uint8_t *)img->planes[AOM_PLANE_V];
608         convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
609                                    srcVStride, dstYStride, dstUStride, dstVStride, mWidth, mHeight);
610     }
611     finishWork(*(int64_t*)img->user_priv, work, std::move(block));
612     block = nullptr;
613     return true;
614 }
615 
drainInternal(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool,const std::unique_ptr<C2Work> & work)616 c2_status_t C2SoftAomDec::drainInternal(
617     uint32_t drainMode, const std::shared_ptr<C2BlockPool>& pool,
618     const std::unique_ptr<C2Work>& work) {
619     if (drainMode == NO_DRAIN) {
620         ALOGW("drain with NO_DRAIN: no-op");
621         return C2_OK;
622     }
623     if (drainMode == DRAIN_CHAIN) {
624         ALOGW("DRAIN_CHAIN not supported");
625         return C2_OMITTED;
626     }
627 
628     if (aom_codec_decode(mCodecCtx, nullptr, 0, nullptr)) {
629         ALOGE("Failed to flush av1 decoder.");
630         return C2_CORRUPTED;
631     }
632 
633     while ((outputBuffer(pool, work))) {
634     }
635 
636     if (drainMode == DRAIN_COMPONENT_WITH_EOS && work &&
637         work->workletsProcessed == 0u) {
638         fillEmptyWork(work);
639     }
640 
641     return C2_OK;
642 }
643 
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)644 c2_status_t C2SoftAomDec::drain(uint32_t drainMode,
645                                 const std::shared_ptr<C2BlockPool>& pool) {
646     return drainInternal(drainMode, pool, nullptr);
647 }
648 
649 class C2SoftAomFactory : public C2ComponentFactory {
650    public:
C2SoftAomFactory()651     C2SoftAomFactory()
652         : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
653               GetCodec2PlatformComponentStore()->getParamReflector())) {}
654 
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)655     virtual c2_status_t createComponent(
656         c2_node_id_t id, std::shared_ptr<C2Component>* const component,
657         std::function<void(C2Component*)> deleter) override {
658         *component = std::shared_ptr<C2Component>(
659             new C2SoftAomDec(COMPONENT_NAME, id,
660                              std::make_shared<C2SoftAomDec::IntfImpl>(mHelper)),
661             deleter);
662         return C2_OK;
663     }
664 
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)665     virtual c2_status_t createInterface(
666         c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
667         std::function<void(C2ComponentInterface*)> deleter) override {
668         *interface = std::shared_ptr<C2ComponentInterface>(
669             new SimpleInterface<C2SoftAomDec::IntfImpl>(
670                 COMPONENT_NAME, id,
671                 std::make_shared<C2SoftAomDec::IntfImpl>(mHelper)),
672             deleter);
673         return C2_OK;
674     }
675 
676     virtual ~C2SoftAomFactory() override = default;
677 
678    private:
679     std::shared_ptr<C2ReflectorHelper> mHelper;
680 };
681 
682 }  // namespace android
683 
684 __attribute__((cfi_canonical_jump_table))
CreateCodec2Factory()685 extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
686     ALOGV("in %s", __func__);
687     return new ::android::C2SoftAomFactory();
688 }
689 
690 __attribute__((cfi_canonical_jump_table))
DestroyCodec2Factory(::C2ComponentFactory * factory)691 extern "C" void DestroyCodec2Factory(::C2ComponentFactory* factory) {
692     ALOGV("in %s", __func__);
693     delete factory;
694 }
695