1 /*
2 * Copyright 2017 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 "C2GoldfishAvcDec"
19 #include <inttypes.h>
20 #include <log/log.h>
21 #include <media/stagefright/foundation/AUtils.h>
22 #include <media/stagefright/foundation/MediaDefs.h>
23
24 #include <C2AllocatorGralloc.h>
25 #include <C2PlatformSupport.h>
26 //#include <android/hardware/graphics/common/1.0/types.h>
27
28 #include <android/hardware/graphics/allocator/3.0/IAllocator.h>
29 #include <android/hardware/graphics/mapper/3.0/IMapper.h>
30 #include <hidl/LegacySupport.h>
31
32 #include <media/stagefright/foundation/MediaDefs.h>
33
34 #include <C2Debug.h>
35 #include <C2PlatformSupport.h>
36 #include <Codec2Mapper.h>
37 #include <SimpleC2Interface.h>
38 #include <goldfish_codec2/store/GoldfishComponentStore.h>
39 #include <gralloc_cb_bp.h>
40
41 #include <color_buffer_utils.h>
42
43 #include "C2GoldfishAvcDec.h"
44
45 #include <mutex>
46
47 #define DEBUG 0
48 #if DEBUG
49 #define DDD(...) ALOGD(__VA_ARGS__)
50 #else
51 #define DDD(...) ((void)0)
52 #endif
53
54 using ::android::hardware::graphics::common::V1_0::BufferUsage;
55 using ::android::hardware::graphics::common::V1_2::PixelFormat;
56
57 namespace android {
58
59 namespace {
60 constexpr size_t kMinInputBufferSize = 6 * 1024 * 1024;
61 constexpr char COMPONENT_NAME[] = "c2.goldfish.h264.decoder";
62 constexpr uint32_t kDefaultOutputDelay = 8;
63 /* avc specification allows for a maximum delay of 16 frames.
64 As soft avc decoder supports interlaced, this delay would be 32 fields.
65 And avc decoder implementation has an additional delay of 2 decode calls.
66 So total maximum output delay is 34 */
67 constexpr uint32_t kMaxOutputDelay = 34;
68 constexpr uint32_t kMinInputBytes = 4;
69
70 static std::mutex s_decoder_count_mutex;
71 static int s_decoder_count = 0;
72
allocateDecoderId()73 int allocateDecoderId() {
74 DDD("calling %s", __func__);
75 std::lock_guard<std::mutex> lock(s_decoder_count_mutex);
76 if (s_decoder_count >= 32 || s_decoder_count < 0) {
77 ALOGE("calling %s failed", __func__);
78 return -1;
79 }
80 ++ s_decoder_count;
81 DDD("calling %s success total decoder %d", __func__, s_decoder_count);
82 return s_decoder_count;;
83 }
84
deAllocateDecoderId()85 bool deAllocateDecoderId() {
86 DDD("calling %s", __func__);
87 std::lock_guard<std::mutex> lock(s_decoder_count_mutex);
88 if (s_decoder_count < 1) {
89 ALOGE("calling %s failed ", __func__);
90 return false;
91 }
92 -- s_decoder_count;
93 DDD("calling %s success total decoder %d", __func__, s_decoder_count);
94 return true;
95 }
96
97
98 } // namespace
99
100 class C2GoldfishAvcDec::IntfImpl : public SimpleInterface<void>::BaseParams {
101 public:
IntfImpl(const std::shared_ptr<C2ReflectorHelper> & helper)102 explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper> &helper)
103 : SimpleInterface<void>::BaseParams(
104 helper, COMPONENT_NAME, C2Component::KIND_DECODER,
105 C2Component::DOMAIN_VIDEO, MEDIA_MIMETYPE_VIDEO_AVC) {
106 noPrivateBuffers(); // TODO: account for our buffers here
107 noInputReferences();
108 noOutputReferences();
109 noInputLatency();
110 noTimeStretch();
111
112 // TODO: Proper support for reorder depth.
113 addParameter(
114 DefineParam(mActualOutputDelay, C2_PARAMKEY_OUTPUT_DELAY)
115 .withDefault(
116 new C2PortActualDelayTuning::output(kDefaultOutputDelay))
117 .withFields({C2F(mActualOutputDelay, value)
118 .inRange(0, kMaxOutputDelay)})
119 .withSetter(
120 Setter<
121 decltype(*mActualOutputDelay)>::StrictValueWithNoDeps)
122 .build());
123
124 // TODO: output latency and reordering
125
126 addParameter(DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
127 .withConstValue(new C2ComponentAttributesSetting(
128 C2Component::ATTRIB_IS_TEMPORAL))
129 .build());
130
131 // coded and output picture size is the same for this codec
132 addParameter(
133 DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
134 .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
135 .withFields({
136 C2F(mSize, width).inRange(2, 4096, 2),
137 C2F(mSize, height).inRange(2, 4096, 2),
138 })
139 .withSetter(SizeSetter)
140 .build());
141
142 addParameter(DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
143 .withDefault(new C2StreamMaxPictureSizeTuning::output(
144 0u, 320, 240))
145 .withFields({
146 C2F(mSize, width).inRange(2, 4096, 2),
147 C2F(mSize, height).inRange(2, 4096, 2),
148 })
149 .withSetter(MaxPictureSizeSetter, mSize)
150 .build());
151
152 addParameter(
153 DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
154 .withDefault(new C2StreamProfileLevelInfo::input(
155 0u, C2Config::PROFILE_AVC_CONSTRAINED_BASELINE,
156 C2Config::LEVEL_AVC_5_2))
157 .withFields(
158 {C2F(mProfileLevel, profile)
159 .oneOf({C2Config::PROFILE_AVC_CONSTRAINED_BASELINE,
160 C2Config::PROFILE_AVC_BASELINE,
161 C2Config::PROFILE_AVC_MAIN,
162 C2Config::PROFILE_AVC_CONSTRAINED_HIGH,
163 C2Config::PROFILE_AVC_PROGRESSIVE_HIGH,
164 C2Config::PROFILE_AVC_HIGH}),
165 C2F(mProfileLevel, level)
166 .oneOf(
167 {C2Config::LEVEL_AVC_1, C2Config::LEVEL_AVC_1B,
168 C2Config::LEVEL_AVC_1_1, C2Config::LEVEL_AVC_1_2,
169 C2Config::LEVEL_AVC_1_3, C2Config::LEVEL_AVC_2,
170 C2Config::LEVEL_AVC_2_1, C2Config::LEVEL_AVC_2_2,
171 C2Config::LEVEL_AVC_3, C2Config::LEVEL_AVC_3_1,
172 C2Config::LEVEL_AVC_3_2, C2Config::LEVEL_AVC_4,
173 C2Config::LEVEL_AVC_4_1, C2Config::LEVEL_AVC_4_2,
174 C2Config::LEVEL_AVC_5, C2Config::LEVEL_AVC_5_1,
175 C2Config::LEVEL_AVC_5_2})})
176 .withSetter(ProfileLevelSetter, mSize)
177 .build());
178
179 addParameter(
180 DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
181 .withDefault(new C2StreamMaxBufferSizeInfo::input(
182 0u, kMinInputBufferSize))
183 .withFields({
184 C2F(mMaxInputSize, value).any(),
185 })
186 .calculatedAs(MaxInputSizeSetter, mMaxSize)
187 .build());
188
189 C2ChromaOffsetStruct locations[1] = {
190 C2ChromaOffsetStruct::ITU_YUV_420_0()};
191 std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
192 C2StreamColorInfo::output::AllocShared(1u, 0u, 8u /* bitDepth */,
193 C2Color::YUV_420);
194 memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
195
196 defaultColorInfo = C2StreamColorInfo::output::AllocShared(
197 {C2ChromaOffsetStruct::ITU_YUV_420_0()}, 0u, 8u /* bitDepth */,
198 C2Color::YUV_420);
199 helper->addStructDescriptors<C2ChromaOffsetStruct>();
200
201 addParameter(DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
202 .withConstValue(defaultColorInfo)
203 .build());
204
205 addParameter(
206 DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
207 .withDefault(new C2StreamColorAspectsTuning::output(
208 0u, C2Color::RANGE_UNSPECIFIED,
209 C2Color::PRIMARIES_UNSPECIFIED,
210 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
211 .withFields({C2F(mDefaultColorAspects, range)
212 .inRange(C2Color::RANGE_UNSPECIFIED,
213 C2Color::RANGE_OTHER),
214 C2F(mDefaultColorAspects, primaries)
215 .inRange(C2Color::PRIMARIES_UNSPECIFIED,
216 C2Color::PRIMARIES_OTHER),
217 C2F(mDefaultColorAspects, transfer)
218 .inRange(C2Color::TRANSFER_UNSPECIFIED,
219 C2Color::TRANSFER_OTHER),
220 C2F(mDefaultColorAspects, matrix)
221 .inRange(C2Color::MATRIX_UNSPECIFIED,
222 C2Color::MATRIX_OTHER)})
223 .withSetter(DefaultColorAspectsSetter)
224 .build());
225
226 addParameter(
227 DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
228 .withDefault(new C2StreamColorAspectsInfo::input(
229 0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
230 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
231 .withFields({C2F(mCodedColorAspects, range)
232 .inRange(C2Color::RANGE_UNSPECIFIED,
233 C2Color::RANGE_OTHER),
234 C2F(mCodedColorAspects, primaries)
235 .inRange(C2Color::PRIMARIES_UNSPECIFIED,
236 C2Color::PRIMARIES_OTHER),
237 C2F(mCodedColorAspects, transfer)
238 .inRange(C2Color::TRANSFER_UNSPECIFIED,
239 C2Color::TRANSFER_OTHER),
240 C2F(mCodedColorAspects, matrix)
241 .inRange(C2Color::MATRIX_UNSPECIFIED,
242 C2Color::MATRIX_OTHER)})
243 .withSetter(CodedColorAspectsSetter)
244 .build());
245
246 addParameter(
247 DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
248 .withDefault(new C2StreamColorAspectsInfo::output(
249 0u, C2Color::RANGE_UNSPECIFIED,
250 C2Color::PRIMARIES_UNSPECIFIED,
251 C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
252 .withFields({C2F(mColorAspects, range)
253 .inRange(C2Color::RANGE_UNSPECIFIED,
254 C2Color::RANGE_OTHER),
255 C2F(mColorAspects, primaries)
256 .inRange(C2Color::PRIMARIES_UNSPECIFIED,
257 C2Color::PRIMARIES_OTHER),
258 C2F(mColorAspects, transfer)
259 .inRange(C2Color::TRANSFER_UNSPECIFIED,
260 C2Color::TRANSFER_OTHER),
261 C2F(mColorAspects, matrix)
262 .inRange(C2Color::MATRIX_UNSPECIFIED,
263 C2Color::MATRIX_OTHER)})
264 .withSetter(ColorAspectsSetter, mDefaultColorAspects,
265 mCodedColorAspects)
266 .build());
267
268 // TODO: support more formats?
269 addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
270 .withConstValue(new C2StreamPixelFormatInfo::output(
271 0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
272 .build());
273 }
SizeSetter(bool mayBlock,const C2P<C2StreamPictureSizeInfo::output> & oldMe,C2P<C2StreamPictureSizeInfo::output> & me)274 static C2R SizeSetter(bool mayBlock,
275 const C2P<C2StreamPictureSizeInfo::output> &oldMe,
276 C2P<C2StreamPictureSizeInfo::output> &me) {
277 (void)mayBlock;
278 DDD("calling sizesetter now %d", oldMe.v.height);
279 DDD("new calling sizesetter now %d", me.v.height);
280
281 C2R res = C2R::Ok();
282 if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
283 ALOGW("w %d is not supported, using old one %d", me.v.width, oldMe.v.width);
284 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
285 me.set().width = oldMe.v.width;
286 }
287 if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
288 ALOGW("h %d is not supported, using old one %d", me.v.height, oldMe.v.height);
289 res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
290 me.set().height = oldMe.v.height;
291 }
292 return res;
293 }
294
295 static C2R
MaxPictureSizeSetter(bool mayBlock,C2P<C2StreamMaxPictureSizeTuning::output> & me,const C2P<C2StreamPictureSizeInfo::output> & size)296 MaxPictureSizeSetter(bool mayBlock,
297 C2P<C2StreamMaxPictureSizeTuning::output> &me,
298 const C2P<C2StreamPictureSizeInfo::output> &size) {
299 (void)mayBlock;
300 // TODO: get max width/height from the size's field helpers vs.
301 // hardcoding
302 me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4096u);
303 me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4096u);
304 return C2R::Ok();
305 }
306
MaxInputSizeSetter(bool mayBlock,C2P<C2StreamMaxBufferSizeInfo::input> & me,const C2P<C2StreamMaxPictureSizeTuning::output> & maxSize)307 static C2R MaxInputSizeSetter(
308 bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input> &me,
309 const C2P<C2StreamMaxPictureSizeTuning::output> &maxSize) {
310 (void)mayBlock;
311 // assume compression ratio of 2
312 me.set().value = c2_max((((maxSize.v.width + 15) / 16) *
313 ((maxSize.v.height + 15) / 16) * 192),
314 kMinInputBufferSize);
315 return C2R::Ok();
316 }
317
318 static C2R
ProfileLevelSetter(bool mayBlock,C2P<C2StreamProfileLevelInfo::input> & me,const C2P<C2StreamPictureSizeInfo::output> & size)319 ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input> &me,
320 const C2P<C2StreamPictureSizeInfo::output> &size) {
321 (void)mayBlock;
322 (void)size;
323 (void)me; // TODO: validate
324 return C2R::Ok();
325 }
326
327 static C2R
DefaultColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsTuning::output> & me)328 DefaultColorAspectsSetter(bool mayBlock,
329 C2P<C2StreamColorAspectsTuning::output> &me) {
330 (void)mayBlock;
331 if (me.v.range > C2Color::RANGE_OTHER) {
332 me.set().range = C2Color::RANGE_OTHER;
333 }
334 if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
335 me.set().primaries = C2Color::PRIMARIES_OTHER;
336 }
337 if (me.v.transfer > C2Color::TRANSFER_OTHER) {
338 me.set().transfer = C2Color::TRANSFER_OTHER;
339 }
340 if (me.v.matrix > C2Color::MATRIX_OTHER) {
341 me.set().matrix = C2Color::MATRIX_OTHER;
342 }
343 DDD("default primaries %d default range %d", me.set().primaries,
344 me.set().range);
345 return C2R::Ok();
346 }
347
348 static C2R
CodedColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsInfo::input> & me)349 CodedColorAspectsSetter(bool mayBlock,
350 C2P<C2StreamColorAspectsInfo::input> &me) {
351 (void)mayBlock;
352 if (me.v.range > C2Color::RANGE_OTHER) {
353 me.set().range = C2Color::RANGE_OTHER;
354 }
355 if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
356 me.set().primaries = C2Color::PRIMARIES_OTHER;
357 }
358 if (me.v.transfer > C2Color::TRANSFER_OTHER) {
359 me.set().transfer = C2Color::TRANSFER_OTHER;
360 }
361 if (me.v.matrix > C2Color::MATRIX_OTHER) {
362 me.set().matrix = C2Color::MATRIX_OTHER;
363 }
364 DDD("coded primaries %d coded range %d", me.set().primaries,
365 me.set().range);
366 return C2R::Ok();
367 }
368
369 static C2R
ColorAspectsSetter(bool mayBlock,C2P<C2StreamColorAspectsInfo::output> & me,const C2P<C2StreamColorAspectsTuning::output> & def,const C2P<C2StreamColorAspectsInfo::input> & coded)370 ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output> &me,
371 const C2P<C2StreamColorAspectsTuning::output> &def,
372 const C2P<C2StreamColorAspectsInfo::input> &coded) {
373 (void)mayBlock;
374 // take default values for all unspecified fields, and coded values for
375 // specified ones
376 DDD("before change primaries %d range %d", me.v.primaries, me.v.range);
377 me.set().range =
378 coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range;
379 me.set().primaries = coded.v.primaries == PRIMARIES_UNSPECIFIED
380 ? def.v.primaries
381 : coded.v.primaries;
382 me.set().transfer = coded.v.transfer == TRANSFER_UNSPECIFIED
383 ? def.v.transfer
384 : coded.v.transfer;
385 me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix
386 : coded.v.matrix;
387
388 DDD("after change primaries %d range %d", me.v.primaries, me.v.range);
389 return C2R::Ok();
390 }
391
getColorAspects_l()392 std::shared_ptr<C2StreamColorAspectsInfo::output> getColorAspects_l() {
393 return mColorAspects;
394 }
395
width() const396 int width() const { return mSize->width; }
397
height() const398 int height() const { return mSize->height; }
399
primaries() const400 int primaries() const { return mColorAspects->primaries; }
401
range() const402 int range() const { return mColorAspects->range; }
403
transfer() const404 int transfer() const { return mColorAspects->transfer; }
405
406 private:
407 std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
408 std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
409 std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize;
410 std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize;
411 std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
412 std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects;
413 std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
414 std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
415 std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
416 };
417
ivd_aligned_malloc(void * ctxt,uint32_t alignment,uint32_t size)418 static void *ivd_aligned_malloc(void *ctxt, uint32_t alignment, uint32_t size) {
419 (void)ctxt;
420 return memalign(alignment, size);
421 }
422
ivd_aligned_free(void * ctxt,void * mem)423 static void ivd_aligned_free(void *ctxt, void *mem) {
424 (void)ctxt;
425 free(mem);
426 }
427
C2GoldfishAvcDec(const char * name,c2_node_id_t id,const std::shared_ptr<IntfImpl> & intfImpl)428 C2GoldfishAvcDec::C2GoldfishAvcDec(const char *name, c2_node_id_t id,
429 const std::shared_ptr<IntfImpl> &intfImpl)
430 : SimpleC2Component(
431 std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
432 mIntf(intfImpl), mOutBufferFlush(nullptr), mWidth(1920), mHeight(1080),
433 mHeaderDecoded(false), mOutIndex(0u) {
434 mWidth = mIntf->width();
435 mHeight = mIntf->height();
436 DDD("creating avc decoder now w %d h %d", mWidth, mHeight);
437 }
438
~C2GoldfishAvcDec()439 C2GoldfishAvcDec::~C2GoldfishAvcDec() { onRelease(); }
440
onInit()441 c2_status_t C2GoldfishAvcDec::onInit() {
442 ALOGD("calling onInit");
443 mId = allocateDecoderId();
444 if (mId <= 0) return C2_NO_MEMORY;
445 status_t err = initDecoder();
446 return err == OK ? C2_OK : C2_CORRUPTED;
447 }
448
onStop()449 c2_status_t C2GoldfishAvcDec::onStop() {
450 if (OK != resetDecoder())
451 return C2_CORRUPTED;
452 resetPlugin();
453 return C2_OK;
454 }
455
onReset()456 void C2GoldfishAvcDec::onReset() { (void)onStop(); }
457
onRelease()458 void C2GoldfishAvcDec::onRelease() {
459 DDD("calling onRelease");
460 if (mId > 0) {
461 deAllocateDecoderId();
462 mId = -1;
463 }
464 deleteContext();
465 if (mOutBlock) {
466 mOutBlock.reset();
467 }
468 }
469
decodeHeaderAfterFlush()470 void C2GoldfishAvcDec::decodeHeaderAfterFlush() {
471 if (mContext && !mCsd0.empty() && !mCsd1.empty()) {
472 mContext->decodeFrame(&(mCsd0[0]), mCsd0.size(), 0);
473 mContext->decodeFrame(&(mCsd1[0]), mCsd1.size(), 0);
474 DDD("resending csd0 and csd1");
475 }
476 }
477
onFlush_sm()478 c2_status_t C2GoldfishAvcDec::onFlush_sm() {
479 if (OK != setFlushMode())
480 return C2_CORRUPTED;
481
482 if (!mContext) {
483 // just ignore if context is not even created
484 return C2_OK;
485 }
486
487 uint32_t bufferSize = mStride * mHeight * 3 / 2;
488 mOutBufferFlush = (uint8_t *)ivd_aligned_malloc(nullptr, 128, bufferSize);
489 if (!mOutBufferFlush) {
490 ALOGE("could not allocate tmp output buffer (for flush) of size %u ",
491 bufferSize);
492 return C2_NO_MEMORY;
493 }
494
495 while (true) {
496 mPts = 0;
497 constexpr bool hasPicture = false;
498 setDecodeArgs(nullptr, nullptr, 0, 0, 0, hasPicture);
499 mImg = mContext->getImage();
500 if (mImg.data == nullptr) {
501 resetPlugin();
502 break;
503 }
504 }
505
506 if (mOutBufferFlush) {
507 ivd_aligned_free(nullptr, mOutBufferFlush);
508 mOutBufferFlush = nullptr;
509 }
510
511 deleteContext();
512 return C2_OK;
513 }
514
sendMetadata()515 void C2GoldfishAvcDec::sendMetadata() {
516 // compare and send if changed
517 MetaDataColorAspects currentMetaData = {1, 0, 0, 0};
518 currentMetaData.primaries = mIntf->primaries();
519 currentMetaData.range = mIntf->range();
520 currentMetaData.transfer = mIntf->transfer();
521
522 DDD("metadata primaries %d range %d transfer %d",
523 (int)(currentMetaData.primaries),
524 (int)(currentMetaData.range),
525 (int)(currentMetaData.transfer)
526 );
527
528 if (mSentMetadata.primaries == currentMetaData.primaries &&
529 mSentMetadata.range == currentMetaData.range &&
530 mSentMetadata.transfer == currentMetaData.transfer) {
531 DDD("metadata is the same, no need to update");
532 return;
533 }
534 std::swap(mSentMetadata, currentMetaData);
535
536 mContext->sendMetadata(&(mSentMetadata));
537 }
538
createDecoder()539 status_t C2GoldfishAvcDec::createDecoder() {
540
541 DDD("creating avc context now w %d h %d", mWidth, mHeight);
542 if (mEnableAndroidNativeBuffers) {
543 mContext.reset(new MediaH264Decoder(RenderMode::RENDER_BY_HOST_GPU));
544 } else {
545 mContext.reset(new MediaH264Decoder(RenderMode::RENDER_BY_GUEST_CPU));
546 }
547 mContext->initH264Context(mWidth, mHeight, mWidth, mHeight,
548 MediaH264Decoder::PixelFormat::YUV420P);
549 return OK;
550 }
551
setParams(size_t stride)552 status_t C2GoldfishAvcDec::setParams(size_t stride) {
553 (void)stride;
554 return OK;
555 }
556
initDecoder()557 status_t C2GoldfishAvcDec::initDecoder() {
558 mStride = ALIGN2(mWidth);
559 mSignalledError = false;
560 resetPlugin();
561
562 return OK;
563 }
564
setDecodeArgs(C2ReadView * inBuffer,C2GraphicView * outBuffer,size_t inOffset,size_t inSize,uint32_t tsMarker,bool hasPicture)565 bool C2GoldfishAvcDec::setDecodeArgs(C2ReadView *inBuffer,
566 C2GraphicView *outBuffer, size_t inOffset,
567 size_t inSize, uint32_t tsMarker, bool hasPicture) {
568 uint32_t displayStride = mStride;
569 (void)inBuffer;
570 (void)inOffset;
571 (void)inSize;
572 (void)tsMarker;
573 if (outBuffer) {
574 C2PlanarLayout layout;
575 layout = outBuffer->layout();
576 displayStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
577 }
578
579 if (inBuffer) {
580 //= tsMarker;
581 mInPBuffer = const_cast<uint8_t *>(inBuffer->data() + inOffset);
582 mInPBufferSize = inSize;
583 mInTsMarker = tsMarker;
584 if (hasPicture) {
585 insertPts(tsMarker, mPts);
586 }
587 }
588
589 // uint32_t displayHeight = mHeight;
590 // size_t lumaSize = displayStride * displayHeight;
591 // size_t chromaSize = lumaSize >> 2;
592
593 if (mStride != displayStride) {
594 mStride = displayStride;
595 if (OK != setParams(mStride))
596 return false;
597 }
598
599 return true;
600 }
601
setFlushMode()602 status_t C2GoldfishAvcDec::setFlushMode() {
603 if (mContext) {
604 mContext->flush();
605 }
606 mHeaderDecoded = false;
607 return OK;
608 }
609
resetDecoder()610 status_t C2GoldfishAvcDec::resetDecoder() {
611 mStride = 0;
612 mSignalledError = false;
613 mHeaderDecoded = false;
614 deleteContext();
615
616 return OK;
617 }
618
resetPlugin()619 void C2GoldfishAvcDec::resetPlugin() {
620 mSignalledOutputEos = false;
621 gettimeofday(&mTimeStart, nullptr);
622 gettimeofday(&mTimeEnd, nullptr);
623 if (mOutBlock) {
624 mOutBlock.reset();
625 }
626 }
627
deleteContext()628 void C2GoldfishAvcDec::deleteContext() {
629 if (mContext) {
630 mContext->destroyH264Context();
631 mContext.reset(nullptr);
632 mPts2Index.clear();
633 mOldPts2Index.clear();
634 mIndex2Pts.clear();
635 }
636 }
637
fillEmptyWork(const std::unique_ptr<C2Work> & work)638 static void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
639 uint32_t flags = 0;
640 if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
641 flags |= C2FrameData::FLAG_END_OF_STREAM;
642 DDD("signalling eos");
643 }
644 DDD("fill empty work");
645 work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
646 work->worklets.front()->output.buffers.clear();
647 work->worklets.front()->output.ordinal = work->input.ordinal;
648 work->workletsProcessed = 1u;
649 }
650
finishWork(uint64_t index,const std::unique_ptr<C2Work> & work)651 void C2GoldfishAvcDec::finishWork(uint64_t index,
652 const std::unique_ptr<C2Work> &work) {
653 std::shared_ptr<C2Buffer> buffer =
654 createGraphicBuffer(std::move(mOutBlock), C2Rect(mWidth, mHeight));
655 mOutBlock = nullptr;
656 {
657 IntfImpl::Lock lock = mIntf->lock();
658 buffer->setInfo(mIntf->getColorAspects_l());
659 }
660
661 class FillWork {
662 public:
663 FillWork(uint32_t flags, C2WorkOrdinalStruct ordinal,
664 const std::shared_ptr<C2Buffer> &buffer)
665 : mFlags(flags), mOrdinal(ordinal), mBuffer(buffer) {}
666 ~FillWork() = default;
667
668 void operator()(const std::unique_ptr<C2Work> &work) {
669 work->worklets.front()->output.flags = (C2FrameData::flags_t)mFlags;
670 work->worklets.front()->output.buffers.clear();
671 work->worklets.front()->output.ordinal = mOrdinal;
672 work->workletsProcessed = 1u;
673 work->result = C2_OK;
674 if (mBuffer) {
675 work->worklets.front()->output.buffers.push_back(mBuffer);
676 }
677 DDD("timestamp = %lld, index = %lld, w/%s buffer",
678 mOrdinal.timestamp.peekll(), mOrdinal.frameIndex.peekll(),
679 mBuffer ? "" : "o");
680 }
681
682 private:
683 const uint32_t mFlags;
684 const C2WorkOrdinalStruct mOrdinal;
685 const std::shared_ptr<C2Buffer> mBuffer;
686 };
687
688 auto fillWork = [buffer](const std::unique_ptr<C2Work> &work) {
689 work->worklets.front()->output.flags = (C2FrameData::flags_t)0;
690 work->worklets.front()->output.buffers.clear();
691 work->worklets.front()->output.buffers.push_back(buffer);
692 work->worklets.front()->output.ordinal = work->input.ordinal;
693 work->workletsProcessed = 1u;
694 };
695 if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
696 bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
697 // TODO: Check if cloneAndSend can be avoided by tracking number of
698 // frames remaining
699 if (eos) {
700 if (buffer) {
701 mOutIndex = index;
702 C2WorkOrdinalStruct outOrdinal = work->input.ordinal;
703 DDD("%s %d: cloneAndSend ", __func__, __LINE__);
704 cloneAndSend(
705 mOutIndex, work,
706 FillWork(C2FrameData::FLAG_INCOMPLETE, outOrdinal, buffer));
707 buffer.reset();
708 }
709 } else {
710 DDD("%s %d: fill", __func__, __LINE__);
711 fillWork(work);
712 }
713 } else {
714 DDD("%s %d: finish", __func__, __LINE__);
715 finish(index, fillWork);
716 }
717 }
718
719 c2_status_t
ensureDecoderState(const std::shared_ptr<C2BlockPool> & pool)720 C2GoldfishAvcDec::ensureDecoderState(const std::shared_ptr<C2BlockPool> &pool) {
721 if (mOutBlock && (mOutBlock->width() != ALIGN2(mWidth) ||
722 mOutBlock->height() != mHeight)) {
723 mOutBlock.reset();
724 }
725 if (!mOutBlock) {
726 const uint32_t format = HAL_PIXEL_FORMAT_YV12;
727 const C2MemoryUsage usage = {(uint64_t)(BufferUsage::VIDEO_DECODER),
728 C2MemoryUsage::CPU_WRITE | C2MemoryUsage::CPU_READ};
729 c2_status_t err = pool->fetchGraphicBlock(ALIGN2(mWidth), mHeight,
730 format, usage, &mOutBlock);
731 if (err != C2_OK) {
732 ALOGE("fetchGraphicBlock for Output failed with status %d", err);
733 return err;
734 }
735 if (mEnableAndroidNativeBuffers) {
736 auto c2Handle = mOutBlock->handle();
737 native_handle_t *grallocHandle =
738 UnwrapNativeCodec2GrallocHandle(c2Handle);
739 mHostColorBufferId = getColorBufferHandle(grallocHandle);
740 DDD("found handle %d", mHostColorBufferId);
741 }
742 DDD("provided (%dx%d) required (%dx%d)", mOutBlock->width(),
743 mOutBlock->height(), ALIGN2(mWidth), mHeight);
744 }
745
746 return C2_OK;
747 }
748
checkMode(const std::shared_ptr<C2BlockPool> & pool)749 void C2GoldfishAvcDec::checkMode(const std::shared_ptr<C2BlockPool> &pool) {
750 mWidth = mIntf->width();
751 mHeight = mIntf->height();
752 //const bool isGraphic = (pool->getLocalId() == C2PlatformAllocatorStore::GRALLOC);
753 const bool isGraphic = (pool->getAllocatorId() & C2Allocator::GRAPHIC);
754 DDD("buffer pool allocator id %x", (int)(pool->getAllocatorId()));
755 if (isGraphic) {
756 uint64_t client_usage = getClientUsage(pool);
757 DDD("client has usage as 0x%llx", client_usage);
758 if (client_usage & BufferUsage::CPU_READ_MASK) {
759 DDD("decoding to guest byte buffer as client has read usage");
760 mEnableAndroidNativeBuffers = false;
761 } else {
762 DDD("decoding to host color buffer");
763 mEnableAndroidNativeBuffers = true;
764 }
765 } else {
766 DDD("decoding to guest byte buffer");
767 mEnableAndroidNativeBuffers = false;
768 }
769 }
770
getVuiParams(h264_image_t & img)771 void C2GoldfishAvcDec::getVuiParams(h264_image_t &img) {
772 VuiColorAspects vuiColorAspects;
773 vuiColorAspects.primaries = img.color_primaries;
774 vuiColorAspects.transfer = img.color_trc;
775 vuiColorAspects.coeffs = img.colorspace;
776 vuiColorAspects.fullRange = img.color_range == 2 ? true : false;
777
778 // convert vui aspects to C2 values if changed
779 if (!(vuiColorAspects == mBitstreamColorAspects)) {
780 mBitstreamColorAspects = vuiColorAspects;
781 ColorAspects sfAspects;
782 C2StreamColorAspectsInfo::input codedAspects = {0u};
783 ColorUtils::convertIsoColorAspectsToCodecAspects(
784 vuiColorAspects.primaries, vuiColorAspects.transfer,
785 vuiColorAspects.coeffs, vuiColorAspects.fullRange, sfAspects);
786 if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) {
787 codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED;
788 }
789 if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) {
790 codedAspects.range = C2Color::RANGE_UNSPECIFIED;
791 }
792 if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) {
793 codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED;
794 }
795 if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) {
796 codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED;
797 }
798 std::vector<std::unique_ptr<C2SettingResult>> failures;
799 (void)mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures);
800 }
801 }
802
copyImageData(h264_image_t & img)803 void C2GoldfishAvcDec::copyImageData(h264_image_t &img) {
804 getVuiParams(img);
805 if (mEnableAndroidNativeBuffers)
806 return;
807
808 auto writeView = mOutBlock->map().get();
809 if (writeView.error()) {
810 ALOGE("graphic view map failed %d", writeView.error());
811 return;
812 }
813 size_t dstYStride = writeView.layout().planes[C2PlanarLayout::PLANE_Y].rowInc;
814 size_t dstUVStride = writeView.layout().planes[C2PlanarLayout::PLANE_U].rowInc;
815
816 uint8_t *pYBuffer = const_cast<uint8_t *>(writeView.data()[C2PlanarLayout::PLANE_Y]);
817 uint8_t *pUBuffer = const_cast<uint8_t *>(writeView.data()[C2PlanarLayout::PLANE_U]);
818 uint8_t *pVBuffer = const_cast<uint8_t *>(writeView.data()[C2PlanarLayout::PLANE_V]);
819
820 for (int i = 0; i < mHeight; ++i) {
821 memcpy(pYBuffer + i * dstYStride, img.data + i * mWidth, mWidth);
822 }
823 for (int i = 0; i < mHeight / 2; ++i) {
824 memcpy(pUBuffer + i * dstUVStride,
825 img.data + mWidth * mHeight + i * mWidth / 2, mWidth / 2);
826 }
827 for (int i = 0; i < mHeight / 2; ++i) {
828 memcpy(pVBuffer + i * dstUVStride,
829 img.data + mWidth * mHeight * 5 / 4 + i * mWidth / 2,
830 mWidth / 2);
831 }
832 }
833
getWorkIndex(uint64_t pts)834 uint64_t C2GoldfishAvcDec::getWorkIndex(uint64_t pts) {
835 if (!mOldPts2Index.empty()) {
836 auto iter = mOldPts2Index.find(pts);
837 if (iter != mOldPts2Index.end()) {
838 auto index = iter->second;
839 DDD("found index %d for pts %" PRIu64, (int)index, pts);
840 return index;
841 }
842 }
843 auto iter = mPts2Index.find(pts);
844 if (iter != mPts2Index.end()) {
845 auto index = iter->second;
846 DDD("found index %d for pts %" PRIu64, (int)index, pts);
847 return index;
848 }
849 DDD("not found index for pts %" PRIu64, pts);
850 return 0;
851 }
852
insertPts(uint32_t work_index,uint64_t pts)853 void C2GoldfishAvcDec::insertPts(uint32_t work_index, uint64_t pts) {
854 auto iter = mPts2Index.find(pts);
855 if (iter != mPts2Index.end()) {
856 // we have a collision here:
857 // apparently, older session is not done yet,
858 // lets save them
859 DDD("inserted to old pts %" PRIu64 " with index %d", pts, (int)iter->second);
860 mOldPts2Index[iter->first] = iter->second;
861 }
862 DDD("inserted pts %" PRIu64 " with index %d", pts, (int)work_index);
863 mIndex2Pts[work_index] = pts;
864 mPts2Index[pts] = work_index;
865 }
866
removePts(uint64_t pts)867 void C2GoldfishAvcDec::removePts(uint64_t pts) {
868 bool found = false;
869 uint64_t index = 0;
870 // note: check old pts first to see
871 // if we have some left over, check them
872 if (!mOldPts2Index.empty()) {
873 auto iter = mOldPts2Index.find(pts);
874 if (iter != mOldPts2Index.end()) {
875 index = iter->second;
876 mOldPts2Index.erase(iter);
877 found = true;
878 }
879 } else {
880 auto iter = mPts2Index.find(pts);
881 if (iter != mPts2Index.end()) {
882 index = iter->second;
883 mPts2Index.erase(iter);
884 found = true;
885 }
886 }
887
888 if (!found) return;
889
890 auto iter2 = mIndex2Pts.find(index);
891 if (iter2 == mIndex2Pts.end()) return;
892 mIndex2Pts.erase(iter2);
893 }
894
895 // TODO: can overall error checking be improved?
896 // TODO: allow configuration of color format and usage for graphic buffers
897 // instead
898 // of hard coding them to HAL_PIXEL_FORMAT_YV12
899 // TODO: pass coloraspects information to surface
900 // TODO: test support for dynamic change in resolution
901 // TODO: verify if the decoder sent back all frames
process(const std::unique_ptr<C2Work> & work,const std::shared_ptr<C2BlockPool> & pool)902 void C2GoldfishAvcDec::process(const std::unique_ptr<C2Work> &work,
903 const std::shared_ptr<C2BlockPool> &pool) {
904 // Initialize output work
905 work->result = C2_OK;
906 work->workletsProcessed = 0u;
907 work->worklets.front()->output.flags = work->input.flags;
908 if (mSignalledError || mSignalledOutputEos) {
909 work->result = C2_BAD_VALUE;
910 return;
911 }
912
913 DDD("process work");
914 if (!mContext) {
915 DDD("creating decoder context to host in process work");
916 checkMode(pool);
917 createDecoder();
918 decodeHeaderAfterFlush();
919 }
920
921 size_t inOffset = 0u;
922 size_t inSize = 0u;
923 uint32_t workIndex = work->input.ordinal.frameIndex.peeku() & 0xFFFFFFFF;
924 mPts = work->input.ordinal.timestamp.peeku();
925 C2ReadView rView = mDummyReadView;
926 if (!work->input.buffers.empty()) {
927 rView =
928 work->input.buffers[0]->data().linearBlocks().front().map().get();
929 inSize = rView.capacity();
930 if (inSize && rView.error()) {
931 ALOGE("read view map failed %d", rView.error());
932 work->result = rView.error();
933 return;
934 }
935 }
936 bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
937 bool hasPicture = (inSize > 0);
938
939 DDD("in buffer attr. size %zu timestamp %d frameindex %d, flags %x", inSize,
940 (int)work->input.ordinal.timestamp.peeku(),
941 (int)work->input.ordinal.frameIndex.peeku(), work->input.flags);
942 size_t inPos = 0;
943 while (inPos < inSize && inSize - inPos >= kMinInputBytes) {
944 if (C2_OK != ensureDecoderState(pool)) {
945 mSignalledError = true;
946 work->workletsProcessed = 1u;
947 work->result = C2_CORRUPTED;
948 return;
949 }
950
951 {
952 // C2GraphicView wView;// = mOutBlock->map().get();
953 // if (wView.error()) {
954 // ALOGE("graphic view map failed %d", wView.error());
955 // work->result = wView.error();
956 // return;
957 //}
958 if (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) {
959 hasPicture = false;
960 }
961 if (!setDecodeArgs(&rView, nullptr, inOffset + inPos,
962 inSize - inPos, workIndex, hasPicture)) {
963 mSignalledError = true;
964 work->workletsProcessed = 1u;
965 work->result = C2_CORRUPTED;
966 return;
967 }
968
969 DDD("flag is %x", work->input.flags);
970 if (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) {
971 if (mCsd0.empty()) {
972 mCsd0.assign(mInPBuffer, mInPBuffer + mInPBufferSize);
973 DDD("assign to csd0 with %d bytpes", mInPBufferSize);
974 } else if (mCsd1.empty()) {
975 mCsd1.assign(mInPBuffer, mInPBuffer + mInPBufferSize);
976 DDD("assign to csd1 with %d bytpes", mInPBufferSize);
977 }
978 }
979
980 bool whChanged = false;
981 if (GoldfishH264Helper::isSpsFrame(mInPBuffer, mInPBufferSize)) {
982 mH264Helper.reset(new GoldfishH264Helper(mWidth, mHeight));
983 whChanged = mH264Helper->decodeHeader(mInPBuffer, mInPBufferSize);
984 if (whChanged) {
985 DDD("w changed from old %d to new %d\n", mWidth, mH264Helper->getWidth());
986 DDD("h changed from old %d to new %d\n", mHeight, mH264Helper->getHeight());
987 if (1) {
988 drainInternal(DRAIN_COMPONENT_NO_EOS, pool, work);
989 resetDecoder();
990 resetPlugin();
991 work->workletsProcessed = 0u;
992 }
993 {
994 mWidth = mH264Helper->getWidth();
995 mHeight = mH264Helper->getHeight();
996 C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
997 std::vector<std::unique_ptr<C2SettingResult>> failures;
998 c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
999 if (err == OK) {
1000 work->worklets.front()->output.configUpdate.push_back(
1001 C2Param::Copy(size));
1002 ensureDecoderState(pool);
1003 } else {
1004 ALOGE("Cannot set width and height");
1005 mSignalledError = true;
1006 work->workletsProcessed = 1u;
1007 work->result = C2_CORRUPTED;
1008 return;
1009 }
1010 }
1011 if (!mContext) {
1012 DDD("creating decoder context to host in process work");
1013 checkMode(pool);
1014 createDecoder();
1015 }
1016 continue;
1017 } // end of whChanged
1018 } // end of isSpsFrame
1019
1020 sendMetadata();
1021
1022 uint32_t delay;
1023 GETTIME(&mTimeStart, nullptr);
1024 TIME_DIFF(mTimeEnd, mTimeStart, delay);
1025 (void)delay;
1026 //(void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
1027 DDD("decoding");
1028 h264_result_t h264Res =
1029 mContext->decodeFrame(mInPBuffer, mInPBufferSize, mPts);
1030 mConsumedBytes = h264Res.bytesProcessed;
1031 DDD("decoding consumed %d", (int)mConsumedBytes);
1032
1033 if (mHostColorBufferId > 0) {
1034 mImg = mContext->renderOnHostAndReturnImageMetadata(
1035 mHostColorBufferId);
1036 } else {
1037 mImg = mContext->getImage();
1038 }
1039 uint32_t decodeTime;
1040 GETTIME(&mTimeEnd, nullptr);
1041 TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
1042 (void)decodeTime;
1043 }
1044
1045 if (mImg.data != nullptr) {
1046 DDD("got data %" PRIu64 " with pts %" PRIu64, getWorkIndex(mImg.pts), mImg.pts);
1047 mHeaderDecoded = true;
1048 copyImageData(mImg);
1049 finishWork(getWorkIndex(mImg.pts), work);
1050 removePts(mImg.pts);
1051 } else {
1052 work->workletsProcessed = 0u;
1053 }
1054
1055 inPos += mConsumedBytes;
1056 }
1057 if (eos) {
1058 DDD("drain because of eos");
1059 drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
1060 mSignalledOutputEos = true;
1061 } else if (!hasPicture) {
1062 DDD("no picture, fill empty work");
1063 fillEmptyWork(work);
1064 }
1065
1066 work->input.buffers.clear();
1067 }
1068
1069 c2_status_t
drainInternal(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool,const std::unique_ptr<C2Work> & work)1070 C2GoldfishAvcDec::drainInternal(uint32_t drainMode,
1071 const std::shared_ptr<C2BlockPool> &pool,
1072 const std::unique_ptr<C2Work> &work) {
1073 if (drainMode == NO_DRAIN) {
1074 ALOGW("drain with NO_DRAIN: no-op");
1075 return C2_OK;
1076 }
1077 if (drainMode == DRAIN_CHAIN) {
1078 ALOGW("DRAIN_CHAIN not supported");
1079 return C2_OMITTED;
1080 }
1081
1082 if (OK != setFlushMode())
1083 return C2_CORRUPTED;
1084 while (true) {
1085 if (C2_OK != ensureDecoderState(pool)) {
1086 mSignalledError = true;
1087 work->workletsProcessed = 1u;
1088 work->result = C2_CORRUPTED;
1089 return C2_CORRUPTED;
1090 }
1091 /*
1092 C2GraphicView wView = mOutBlock->map().get();
1093 if (wView.error()) {
1094 ALOGE("graphic view map failed %d", wView.error());
1095 return C2_CORRUPTED;
1096 }
1097 if (!setDecodeArgs(nullptr, &wView, 0, 0, 0)) {
1098 mSignalledError = true;
1099 work->workletsProcessed = 1u;
1100 return C2_CORRUPTED;
1101 }
1102 */
1103
1104 if (mHostColorBufferId > 0) {
1105 mImg = mContext->renderOnHostAndReturnImageMetadata(
1106 mHostColorBufferId);
1107 } else {
1108 mImg = mContext->getImage();
1109 }
1110
1111 // TODO: maybe keep rendering to screen
1112 // mImg = mContext->getImage();
1113 if (mImg.data != nullptr) {
1114 DDD("got data in drain mode %" PRIu64 " with pts %" PRIu64, getWorkIndex(mImg.pts), mImg.pts);
1115 copyImageData(mImg);
1116 finishWork(getWorkIndex(mImg.pts), work);
1117 removePts(mImg.pts);
1118 } else {
1119 fillEmptyWork(work);
1120 break;
1121 }
1122 }
1123
1124 return C2_OK;
1125 }
1126
drain(uint32_t drainMode,const std::shared_ptr<C2BlockPool> & pool)1127 c2_status_t C2GoldfishAvcDec::drain(uint32_t drainMode,
1128 const std::shared_ptr<C2BlockPool> &pool) {
1129 DDD("drainInternal because of drain");
1130 return drainInternal(drainMode, pool, nullptr);
1131 }
1132
1133 class C2GoldfishAvcDecFactory : public C2ComponentFactory {
1134 public:
C2GoldfishAvcDecFactory()1135 C2GoldfishAvcDecFactory()
1136 : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
1137 GoldfishComponentStore::Create()->getParamReflector())) {}
1138
1139 virtual c2_status_t
createComponent(c2_node_id_t id,std::shared_ptr<C2Component> * const component,std::function<void (C2Component *)> deleter)1140 createComponent(c2_node_id_t id,
1141 std::shared_ptr<C2Component> *const component,
1142 std::function<void(C2Component *)> deleter) override {
1143 *component = std::shared_ptr<C2Component>(
1144 new C2GoldfishAvcDec(
1145 COMPONENT_NAME, id,
1146 std::make_shared<C2GoldfishAvcDec::IntfImpl>(mHelper)),
1147 deleter);
1148 return C2_OK;
1149 }
1150
createInterface(c2_node_id_t id,std::shared_ptr<C2ComponentInterface> * const interface,std::function<void (C2ComponentInterface *)> deleter)1151 virtual c2_status_t createInterface(
1152 c2_node_id_t id, std::shared_ptr<C2ComponentInterface> *const interface,
1153 std::function<void(C2ComponentInterface *)> deleter) override {
1154 *interface = std::shared_ptr<C2ComponentInterface>(
1155 new SimpleInterface<C2GoldfishAvcDec::IntfImpl>(
1156 COMPONENT_NAME, id,
1157 std::make_shared<C2GoldfishAvcDec::IntfImpl>(mHelper)),
1158 deleter);
1159 return C2_OK;
1160 }
1161
1162 virtual ~C2GoldfishAvcDecFactory() override = default;
1163
1164 private:
1165 std::shared_ptr<C2ReflectorHelper> mHelper;
1166 };
1167
1168 } // namespace android
1169
CreateCodec2Factory()1170 extern "C" ::C2ComponentFactory *CreateCodec2Factory() {
1171 DDD("in %s", __func__);
1172 return new ::android::C2GoldfishAvcDecFactory();
1173 }
1174
DestroyCodec2Factory(::C2ComponentFactory * factory)1175 extern "C" void DestroyCodec2Factory(::C2ComponentFactory *factory) {
1176 DDD("in %s", __func__);
1177 delete factory;
1178 }
1179