blob: 670923bc05d31a527aaa7792fc46388b46c825f6 [file] [log] [blame]
Wonsik Kim469c8342019-04-11 16:46:09 -07001/*
2 * Copyright 2019, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "CCodecBuffers"
19#include <utils/Log.h>
20
Songyue Han1e6769b2023-08-30 18:09:27 +000021#include <C2AllocatorGralloc.h>
Wonsik Kim469c8342019-04-11 16:46:09 -070022#include <C2PlatformSupport.h>
23
24#include <media/stagefright/foundation/ADebug.h>
Wonsik Kim6f23cfc2021-09-24 05:45:52 -070025#include <media/stagefright/foundation/MediaDefs.h>
Wonsik Kim469c8342019-04-11 16:46:09 -070026#include <media/stagefright/MediaCodecConstants.h>
Wonsik Kim155d5cb2019-10-09 12:49:49 -070027#include <media/stagefright/SkipCutBuffer.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070028#include <mediadrm/ICrypto.h>
Wonsik Kim469c8342019-04-11 16:46:09 -070029
30#include "CCodecBuffers.h"
Wonsik Kimd79ee1f2020-08-27 17:41:56 -070031#include "Codec2Mapper.h"
Wonsik Kim469c8342019-04-11 16:46:09 -070032
33namespace android {
34
35namespace {
36
My Nameac29e592022-03-28 13:53:32 -070037constexpr uint32_t PIXEL_FORMAT_UNKNOWN = 0;
38
David Stevens94b608f2021-07-29 15:04:14 +090039sp<GraphicBlockBuffer> AllocateInputGraphicBuffer(
Wonsik Kim469c8342019-04-11 16:46:09 -070040 const std::shared_ptr<C2BlockPool> &pool,
41 const sp<AMessage> &format,
42 uint32_t pixelFormat,
43 const C2MemoryUsage &usage,
44 const std::shared_ptr<LocalBufferPool> &localBufferPool) {
45 int32_t width, height;
46 if (!format->findInt32("width", &width) || !format->findInt32("height", &height)) {
47 ALOGD("format lacks width or height");
48 return nullptr;
49 }
50
David Stevens94b608f2021-07-29 15:04:14 +090051 int64_t usageValue = 0;
52 (void)format->findInt64("android._C2MemoryUsage", &usageValue);
53 C2MemoryUsage fullUsage{usageValue | usage.expected};
54
Wonsik Kim469c8342019-04-11 16:46:09 -070055 std::shared_ptr<C2GraphicBlock> block;
56 c2_status_t err = pool->fetchGraphicBlock(
David Stevens94b608f2021-07-29 15:04:14 +090057 width, height, pixelFormat, fullUsage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -070058 if (err != C2_OK) {
59 ALOGD("fetch graphic block failed: %d", err);
60 return nullptr;
61 }
62
63 return GraphicBlockBuffer::Allocate(
64 format,
65 block,
66 [localBufferPool](size_t capacity) {
67 return localBufferPool->newBuffer(capacity);
68 });
69}
70
71} // namespace
72
73// CCodecBuffers
74
75void CCodecBuffers::setFormat(const sp<AMessage> &format) {
76 CHECK(format != nullptr);
77 mFormat = format;
78}
79
80sp<AMessage> CCodecBuffers::dupFormat() {
81 return mFormat != nullptr ? mFormat->dup() : nullptr;
82}
83
84void CCodecBuffers::handleImageData(const sp<Codec2Buffer> &buffer) {
85 sp<ABuffer> imageDataCandidate = buffer->getImageData();
86 if (imageDataCandidate == nullptr) {
Wonsik Kim4a3c0462021-03-09 15:45:05 -080087 if (mFormatWithImageData) {
88 // We previously sent the format with image data, so use the same format.
89 buffer->setFormat(mFormatWithImageData);
90 }
Wonsik Kim469c8342019-04-11 16:46:09 -070091 return;
92 }
Wonsik Kim4a3c0462021-03-09 15:45:05 -080093 if (!mLastImageData
94 || imageDataCandidate->size() != mLastImageData->size()
95 || memcmp(imageDataCandidate->data(),
96 mLastImageData->data(),
97 mLastImageData->size()) != 0) {
Wonsik Kim469c8342019-04-11 16:46:09 -070098 ALOGD("[%s] updating image-data", mName);
Wonsik Kim4a3c0462021-03-09 15:45:05 -080099 mFormatWithImageData = dupFormat();
100 mLastImageData = imageDataCandidate;
101 mFormatWithImageData->setBuffer("image-data", imageDataCandidate);
Wonsik Kim469c8342019-04-11 16:46:09 -0700102 MediaImage2 *img = (MediaImage2*)imageDataCandidate->data();
103 if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
104 int32_t stride = img->mPlane[0].mRowInc;
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800105 mFormatWithImageData->setInt32(KEY_STRIDE, stride);
Vinay Kaliaef5fc712021-09-15 23:59:50 +0000106 mFormatWithImageData->setInt32(KEY_WIDTH, img->mWidth);
107 mFormatWithImageData->setInt32(KEY_HEIGHT, img->mHeight);
108 ALOGD("[%s] updating stride = %d, width: %d, height: %d",
109 mName, stride, img->mWidth, img->mHeight);
Wonsik Kim469c8342019-04-11 16:46:09 -0700110 if (img->mNumPlanes > 1 && stride > 0) {
Taehwan Kimfd9b8092020-09-17 12:26:40 +0900111 int64_t offsetDelta =
112 (int64_t)img->mPlane[1].mOffset - (int64_t)img->mPlane[0].mOffset;
113 int32_t vstride = int32_t(offsetDelta / stride);
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800114 mFormatWithImageData->setInt32(KEY_SLICE_HEIGHT, vstride);
Wonsik Kim469c8342019-04-11 16:46:09 -0700115 ALOGD("[%s] updating vstride = %d", mName, vstride);
Wonsik Kim2eb06312020-12-03 11:07:58 -0800116 buffer->setRange(
117 img->mPlane[0].mOffset,
118 buffer->size() - img->mPlane[0].mOffset);
Wonsik Kim469c8342019-04-11 16:46:09 -0700119 }
120 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700121 }
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800122 buffer->setFormat(mFormatWithImageData);
Wonsik Kim469c8342019-04-11 16:46:09 -0700123}
124
Songyue Han1e6769b2023-08-30 18:09:27 +0000125uint32_t CCodecBuffers::getPixelFormatIfApplicable() { return PIXEL_FORMAT_UNKNOWN; }
126
127bool CCodecBuffers::resetPixelFormatIfApplicable() { return false; }
128
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700129// InputBuffers
130
131sp<Codec2Buffer> InputBuffers::cloneAndReleaseBuffer(const sp<MediaCodecBuffer> &buffer) {
132 sp<Codec2Buffer> copy = createNewBuffer();
133 if (copy == nullptr) {
134 return nullptr;
135 }
136 std::shared_ptr<C2Buffer> c2buffer;
137 if (!releaseBuffer(buffer, &c2buffer, true)) {
138 return nullptr;
139 }
140 if (!copy->canCopy(c2buffer)) {
141 return nullptr;
142 }
143 if (!copy->copy(c2buffer)) {
144 return nullptr;
145 }
Wonsik Kimfb5ca492021-08-11 14:18:19 -0700146 copy->meta()->extend(buffer->meta());
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700147 return copy;
148}
149
Wonsik Kim469c8342019-04-11 16:46:09 -0700150// OutputBuffers
151
Wonsik Kim41d83432020-04-27 16:40:49 -0700152OutputBuffers::OutputBuffers(const char *componentName, const char *name)
153 : CCodecBuffers(componentName, name) { }
154
155OutputBuffers::~OutputBuffers() = default;
156
Wonsik Kim469c8342019-04-11 16:46:09 -0700157void OutputBuffers::initSkipCutBuffer(
158 int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount) {
159 CHECK(mSkipCutBuffer == nullptr);
160 mDelay = delay;
161 mPadding = padding;
162 mSampleRate = sampleRate;
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700163 mChannelCount = channelCount;
164 setSkipCutBuffer(delay, padding);
Wonsik Kim469c8342019-04-11 16:46:09 -0700165}
166
167void OutputBuffers::updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount) {
168 if (mSkipCutBuffer == nullptr) {
169 return;
170 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700171 if (mSampleRate == sampleRate && mChannelCount == channelCount) {
172 return;
173 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700174 int32_t delay = mDelay;
175 int32_t padding = mPadding;
176 if (sampleRate != mSampleRate) {
177 delay = ((int64_t)delay * sampleRate) / mSampleRate;
178 padding = ((int64_t)padding * sampleRate) / mSampleRate;
179 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700180 mSampleRate = sampleRate;
181 mChannelCount = channelCount;
182 setSkipCutBuffer(delay, padding);
Wonsik Kim469c8342019-04-11 16:46:09 -0700183}
184
Wonsik Kim3b4349a2020-11-10 11:54:15 -0800185void OutputBuffers::updateSkipCutBuffer(const sp<AMessage> &format) {
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700186 AString mediaType;
187 if (format->findString(KEY_MIME, &mediaType)
188 && mediaType == MIMETYPE_AUDIO_RAW) {
189 int32_t channelCount;
190 int32_t sampleRate;
191 if (format->findInt32(KEY_CHANNEL_COUNT, &channelCount)
192 && format->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
193 updateSkipCutBuffer(sampleRate, channelCount);
194 }
195 }
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700196}
197
Wonsik Kim469c8342019-04-11 16:46:09 -0700198void OutputBuffers::submit(const sp<MediaCodecBuffer> &buffer) {
199 if (mSkipCutBuffer != nullptr) {
200 mSkipCutBuffer->submit(buffer);
201 }
202}
203
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700204void OutputBuffers::setSkipCutBuffer(int32_t skip, int32_t cut) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700205 if (mSkipCutBuffer != nullptr) {
206 size_t prevSize = mSkipCutBuffer->size();
207 if (prevSize != 0u) {
208 ALOGD("[%s] Replacing SkipCutBuffer holding %zu bytes", mName, prevSize);
209 }
210 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700211 mSkipCutBuffer = new SkipCutBuffer(skip, cut, mChannelCount);
Wonsik Kim469c8342019-04-11 16:46:09 -0700212}
213
Wonsik Kim6f23cfc2021-09-24 05:45:52 -0700214bool OutputBuffers::convert(
215 const std::shared_ptr<C2Buffer> &src, sp<Codec2Buffer> *dst) {
Wonsik Kim360ba0a2022-05-23 15:38:21 -0700216 if (src && src->data().type() != C2BufferData::LINEAR) {
Wonsik Kim6f23cfc2021-09-24 05:45:52 -0700217 return false;
218 }
219 int32_t configEncoding = kAudioEncodingPcm16bit;
220 int32_t codecEncoding = kAudioEncodingPcm16bit;
221 if (mFormat->findInt32("android._codec-pcm-encoding", &codecEncoding)
222 && mFormat->findInt32("android._config-pcm-encoding", &configEncoding)) {
223 if (mSrcEncoding != codecEncoding || mDstEncoding != configEncoding) {
224 if (codecEncoding != configEncoding) {
225 mDataConverter = AudioConverter::Create(
226 (AudioEncoding)codecEncoding, (AudioEncoding)configEncoding);
227 ALOGD_IF(mDataConverter, "[%s] Converter created from %d to %d",
228 mName, codecEncoding, configEncoding);
229 mFormatWithConverter = mFormat->dup();
230 mFormatWithConverter->setInt32(KEY_PCM_ENCODING, configEncoding);
231 } else {
232 mDataConverter = nullptr;
233 mFormatWithConverter = nullptr;
234 }
235 mSrcEncoding = codecEncoding;
236 mDstEncoding = configEncoding;
237 }
238 if (int encoding; !mFormat->findInt32(KEY_PCM_ENCODING, &encoding)
239 || encoding != mDstEncoding) {
240 }
241 }
242 if (!mDataConverter) {
243 return false;
244 }
Wonsik Kim360ba0a2022-05-23 15:38:21 -0700245 sp<MediaCodecBuffer> srcBuffer;
246 if (src) {
247 srcBuffer = ConstLinearBlockBuffer::Allocate(mFormat, src);
248 } else {
249 srcBuffer = new MediaCodecBuffer(mFormat, new ABuffer(0));
250 }
Wonsik Kim6f23cfc2021-09-24 05:45:52 -0700251 if (!srcBuffer) {
252 return false;
253 }
Greg Kaiser92dc4542021-10-08 06:58:19 -0700254 if (!*dst) {
Wonsik Kim6f23cfc2021-09-24 05:45:52 -0700255 *dst = new Codec2Buffer(
256 mFormat,
257 new ABuffer(mDataConverter->targetSize(srcBuffer->size())));
258 }
259 sp<MediaCodecBuffer> dstBuffer = *dst;
260 status_t err = mDataConverter->convert(srcBuffer, dstBuffer);
261 if (err != OK) {
262 ALOGD("[%s] buffer conversion failed: %d", mName, err);
263 return false;
264 }
265 dstBuffer->setFormat(mFormatWithConverter);
266 return true;
267}
268
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700269void OutputBuffers::clearStash() {
270 mPending.clear();
271 mReorderStash.clear();
272 mDepth = 0;
273 mKey = C2Config::ORDINAL;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700274}
275
276void OutputBuffers::flushStash() {
277 for (StashEntry& e : mPending) {
278 e.notify = false;
279 }
280 for (StashEntry& e : mReorderStash) {
281 e.notify = false;
282 }
283}
284
285uint32_t OutputBuffers::getReorderDepth() const {
286 return mDepth;
287}
288
289void OutputBuffers::setReorderDepth(uint32_t depth) {
290 mPending.splice(mPending.end(), mReorderStash);
291 mDepth = depth;
292}
293
294void OutputBuffers::setReorderKey(C2Config::ordinal_key_t key) {
295 mPending.splice(mPending.end(), mReorderStash);
296 mKey = key;
297}
298
299void OutputBuffers::pushToStash(
300 const std::shared_ptr<C2Buffer>& buffer,
301 bool notify,
302 int64_t timestamp,
303 int32_t flags,
304 const sp<AMessage>& format,
305 const C2WorkOrdinalStruct& ordinal) {
My Nameac29e592022-03-28 13:53:32 -0700306 bool eos = flags & BUFFER_FLAG_END_OF_STREAM;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700307 if (!buffer && eos) {
308 // TRICKY: we may be violating ordering of the stash here. Because we
309 // don't expect any more emplace() calls after this, the ordering should
310 // not matter.
311 mReorderStash.emplace_back(
312 buffer, notify, timestamp, flags, format, ordinal);
313 } else {
My Nameac29e592022-03-28 13:53:32 -0700314 flags = flags & ~BUFFER_FLAG_END_OF_STREAM;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700315 auto it = mReorderStash.begin();
316 for (; it != mReorderStash.end(); ++it) {
317 if (less(ordinal, it->ordinal)) {
318 break;
319 }
320 }
321 mReorderStash.emplace(it,
322 buffer, notify, timestamp, flags, format, ordinal);
323 if (eos) {
324 mReorderStash.back().flags =
My Nameac29e592022-03-28 13:53:32 -0700325 mReorderStash.back().flags | BUFFER_FLAG_END_OF_STREAM;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700326 }
327 }
328 while (!mReorderStash.empty() && mReorderStash.size() > mDepth) {
329 mPending.push_back(mReorderStash.front());
330 mReorderStash.pop_front();
331 }
332 ALOGV("[%s] %s: pushToStash -- pending size = %zu", mName, __func__, mPending.size());
333}
334
335OutputBuffers::BufferAction OutputBuffers::popFromStashAndRegister(
336 std::shared_ptr<C2Buffer>* c2Buffer,
337 size_t* index,
338 sp<MediaCodecBuffer>* outBuffer) {
339 if (mPending.empty()) {
340 return SKIP;
341 }
342
343 // Retrieve the first entry.
344 StashEntry &entry = mPending.front();
345
346 *c2Buffer = entry.buffer;
347 sp<AMessage> outputFormat = entry.format;
348
Wonsik Kim3b4349a2020-11-10 11:54:15 -0800349 if (entry.notify && mFormat != outputFormat) {
350 updateSkipCutBuffer(outputFormat);
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800351 // Trigger image data processing to the new format
352 mLastImageData.clear();
Wonsik Kim3b4349a2020-11-10 11:54:15 -0800353 ALOGV("[%s] popFromStashAndRegister: output format reference changed: %p -> %p",
354 mName, mFormat.get(), outputFormat.get());
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800355 ALOGD("[%s] popFromStashAndRegister: at %lldus, output format changed to %s",
356 mName, (long long)entry.timestamp, outputFormat->debugString().c_str());
Wonsik Kim3b4349a2020-11-10 11:54:15 -0800357 setFormat(outputFormat);
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700358 }
359
360 // Flushing mReorderStash because no other buffers should come after output
361 // EOS.
My Nameac29e592022-03-28 13:53:32 -0700362 if (entry.flags & BUFFER_FLAG_END_OF_STREAM) {
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700363 // Flush reorder stash
364 setReorderDepth(0);
365 }
366
367 if (!entry.notify) {
368 mPending.pop_front();
369 return DISCARD;
370 }
371
372 // Try to register the buffer.
373 status_t err = registerBuffer(*c2Buffer, index, outBuffer);
374 if (err != OK) {
375 if (err != WOULD_BLOCK) {
376 return REALLOCATE;
377 }
378 return RETRY;
379 }
380
381 // Append information from the front stash entry to outBuffer.
382 (*outBuffer)->meta()->setInt64("timeUs", entry.timestamp);
383 (*outBuffer)->meta()->setInt32("flags", entry.flags);
Byeongjo Park2eef13e2020-06-12 17:24:21 +0900384 (*outBuffer)->meta()->setInt64("frameIndex", entry.ordinal.frameIndex.peekll());
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700385 ALOGV("[%s] popFromStashAndRegister: "
386 "out buffer index = %zu [%p] => %p + %zu (%lld)",
387 mName, *index, outBuffer->get(),
388 (*outBuffer)->data(), (*outBuffer)->size(),
389 (long long)entry.timestamp);
390
391 // The front entry of mPending will be removed now that the registration
392 // succeeded.
393 mPending.pop_front();
394 return NOTIFY_CLIENT;
395}
396
397bool OutputBuffers::popPending(StashEntry *entry) {
398 if (mPending.empty()) {
399 return false;
400 }
401 *entry = mPending.front();
402 mPending.pop_front();
403 return true;
404}
405
406void OutputBuffers::deferPending(const OutputBuffers::StashEntry &entry) {
407 mPending.push_front(entry);
408}
409
410bool OutputBuffers::hasPending() const {
411 return !mPending.empty();
412}
413
414bool OutputBuffers::less(
415 const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2) const {
416 switch (mKey) {
417 case C2Config::ORDINAL: return o1.frameIndex < o2.frameIndex;
418 case C2Config::TIMESTAMP: return o1.timestamp < o2.timestamp;
419 case C2Config::CUSTOM: return o1.customOrdinal < o2.customOrdinal;
420 default:
421 ALOGD("Unrecognized key; default to timestamp");
422 return o1.frameIndex < o2.frameIndex;
423 }
424}
425
Wonsik Kim469c8342019-04-11 16:46:09 -0700426// LocalBufferPool
427
Wonsik Kim41d83432020-04-27 16:40:49 -0700428constexpr size_t kInitialPoolCapacity = kMaxLinearBufferSize;
429constexpr size_t kMaxPoolCapacity = kMaxLinearBufferSize * 32;
430
431std::shared_ptr<LocalBufferPool> LocalBufferPool::Create() {
432 return std::shared_ptr<LocalBufferPool>(new LocalBufferPool(kInitialPoolCapacity));
Wonsik Kim469c8342019-04-11 16:46:09 -0700433}
434
435sp<ABuffer> LocalBufferPool::newBuffer(size_t capacity) {
436 Mutex::Autolock lock(mMutex);
437 auto it = std::find_if(
438 mPool.begin(), mPool.end(),
439 [capacity](const std::vector<uint8_t> &vec) {
440 return vec.capacity() >= capacity;
441 });
442 if (it != mPool.end()) {
443 sp<ABuffer> buffer = new VectorBuffer(std::move(*it), shared_from_this());
444 mPool.erase(it);
445 return buffer;
446 }
447 if (mUsedSize + capacity > mPoolCapacity) {
448 while (!mPool.empty()) {
449 mUsedSize -= mPool.back().capacity();
450 mPool.pop_back();
451 }
Wonsik Kim41d83432020-04-27 16:40:49 -0700452 while (mUsedSize + capacity > mPoolCapacity && mPoolCapacity * 2 <= kMaxPoolCapacity) {
453 ALOGD("Increasing local buffer pool capacity from %zu to %zu",
454 mPoolCapacity, mPoolCapacity * 2);
455 mPoolCapacity *= 2;
456 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700457 if (mUsedSize + capacity > mPoolCapacity) {
458 ALOGD("mUsedSize = %zu, capacity = %zu, mPoolCapacity = %zu",
459 mUsedSize, capacity, mPoolCapacity);
460 return nullptr;
461 }
462 }
463 std::vector<uint8_t> vec(capacity);
464 mUsedSize += vec.capacity();
465 return new VectorBuffer(std::move(vec), shared_from_this());
466}
467
468LocalBufferPool::VectorBuffer::VectorBuffer(
469 std::vector<uint8_t> &&vec, const std::shared_ptr<LocalBufferPool> &pool)
470 : ABuffer(vec.data(), vec.capacity()),
471 mVec(std::move(vec)),
472 mPool(pool) {
473}
474
475LocalBufferPool::VectorBuffer::~VectorBuffer() {
476 std::shared_ptr<LocalBufferPool> pool = mPool.lock();
477 if (pool) {
478 // If pool is alive, return the vector back to the pool so that
479 // it can be recycled.
480 pool->returnVector(std::move(mVec));
481 }
482}
483
484void LocalBufferPool::returnVector(std::vector<uint8_t> &&vec) {
485 Mutex::Autolock lock(mMutex);
486 mPool.push_front(std::move(vec));
487}
488
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700489// FlexBuffersImpl
490
Wonsik Kim469c8342019-04-11 16:46:09 -0700491size_t FlexBuffersImpl::assignSlot(const sp<Codec2Buffer> &buffer) {
492 for (size_t i = 0; i < mBuffers.size(); ++i) {
493 if (mBuffers[i].clientBuffer == nullptr
494 && mBuffers[i].compBuffer.expired()) {
495 mBuffers[i].clientBuffer = buffer;
496 return i;
497 }
498 }
499 mBuffers.push_back({ buffer, std::weak_ptr<C2Buffer>() });
500 return mBuffers.size() - 1;
501}
502
Wonsik Kim469c8342019-04-11 16:46:09 -0700503bool FlexBuffersImpl::releaseSlot(
504 const sp<MediaCodecBuffer> &buffer,
505 std::shared_ptr<C2Buffer> *c2buffer,
506 bool release) {
507 sp<Codec2Buffer> clientBuffer;
508 size_t index = mBuffers.size();
509 for (size_t i = 0; i < mBuffers.size(); ++i) {
510 if (mBuffers[i].clientBuffer == buffer) {
511 clientBuffer = mBuffers[i].clientBuffer;
512 if (release) {
513 mBuffers[i].clientBuffer.clear();
514 }
515 index = i;
516 break;
517 }
518 }
519 if (clientBuffer == nullptr) {
520 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
521 return false;
522 }
523 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
524 if (!result) {
525 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700526 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700527 mBuffers[index].compBuffer = result;
528 }
529 if (c2buffer) {
530 *c2buffer = result;
531 }
532 return true;
533}
534
535bool FlexBuffersImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
536 for (size_t i = 0; i < mBuffers.size(); ++i) {
537 std::shared_ptr<C2Buffer> compBuffer =
538 mBuffers[i].compBuffer.lock();
539 if (!compBuffer || compBuffer != c2buffer) {
540 continue;
541 }
542 mBuffers[i].compBuffer.reset();
543 ALOGV("[%s] codec released buffer #%zu", mName, i);
544 return true;
545 }
546 ALOGV("[%s] codec released an unknown buffer", mName);
547 return false;
548}
549
550void FlexBuffersImpl::flush() {
551 ALOGV("[%s] buffers are flushed %zu", mName, mBuffers.size());
552 mBuffers.clear();
553}
554
Wonsik Kim0487b782020-10-28 11:45:50 -0700555size_t FlexBuffersImpl::numActiveSlots() const {
Wonsik Kim469c8342019-04-11 16:46:09 -0700556 return std::count_if(
557 mBuffers.begin(), mBuffers.end(),
558 [](const Entry &entry) {
Wonsik Kim0487b782020-10-28 11:45:50 -0700559 return (entry.clientBuffer != nullptr
560 || !entry.compBuffer.expired());
Wonsik Kim469c8342019-04-11 16:46:09 -0700561 });
562}
563
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700564size_t FlexBuffersImpl::numComponentBuffers() const {
565 return std::count_if(
566 mBuffers.begin(), mBuffers.end(),
567 [](const Entry &entry) {
568 return !entry.compBuffer.expired();
569 });
570}
571
Wonsik Kim469c8342019-04-11 16:46:09 -0700572// BuffersArrayImpl
573
574void BuffersArrayImpl::initialize(
575 const FlexBuffersImpl &impl,
576 size_t minSize,
577 std::function<sp<Codec2Buffer>()> allocate) {
578 mImplName = impl.mImplName + "[N]";
579 mName = mImplName.c_str();
580 for (size_t i = 0; i < impl.mBuffers.size(); ++i) {
581 sp<Codec2Buffer> clientBuffer = impl.mBuffers[i].clientBuffer;
582 bool ownedByClient = (clientBuffer != nullptr);
583 if (!ownedByClient) {
584 clientBuffer = allocate();
585 }
586 mBuffers.push_back({ clientBuffer, impl.mBuffers[i].compBuffer, ownedByClient });
587 }
588 ALOGV("[%s] converted %zu buffers to array mode of %zu", mName, mBuffers.size(), minSize);
589 for (size_t i = impl.mBuffers.size(); i < minSize; ++i) {
590 mBuffers.push_back({ allocate(), std::weak_ptr<C2Buffer>(), false });
591 }
592}
593
594status_t BuffersArrayImpl::grabBuffer(
595 size_t *index,
596 sp<Codec2Buffer> *buffer,
597 std::function<bool(const sp<Codec2Buffer> &)> match) {
598 // allBuffersDontMatch remains true if all buffers are available but
599 // match() returns false for every buffer.
600 bool allBuffersDontMatch = true;
601 for (size_t i = 0; i < mBuffers.size(); ++i) {
602 if (!mBuffers[i].ownedByClient && mBuffers[i].compBuffer.expired()) {
603 if (match(mBuffers[i].clientBuffer)) {
604 mBuffers[i].ownedByClient = true;
605 *buffer = mBuffers[i].clientBuffer;
606 (*buffer)->meta()->clear();
607 (*buffer)->setRange(0, (*buffer)->capacity());
608 *index = i;
609 return OK;
610 }
611 } else {
612 allBuffersDontMatch = false;
613 }
614 }
615 return allBuffersDontMatch ? NO_MEMORY : WOULD_BLOCK;
616}
617
618bool BuffersArrayImpl::returnBuffer(
619 const sp<MediaCodecBuffer> &buffer,
620 std::shared_ptr<C2Buffer> *c2buffer,
621 bool release) {
622 sp<Codec2Buffer> clientBuffer;
623 size_t index = mBuffers.size();
624 for (size_t i = 0; i < mBuffers.size(); ++i) {
625 if (mBuffers[i].clientBuffer == buffer) {
626 if (!mBuffers[i].ownedByClient) {
627 ALOGD("[%s] Client returned a buffer it does not own according to our record: %zu",
628 mName, i);
629 }
630 clientBuffer = mBuffers[i].clientBuffer;
631 if (release) {
632 mBuffers[i].ownedByClient = false;
633 }
634 index = i;
635 break;
636 }
637 }
638 if (clientBuffer == nullptr) {
639 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
640 return false;
641 }
642 ALOGV("[%s] %s: matching buffer found (index=%zu)", mName, __func__, index);
643 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
644 if (!result) {
645 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700646 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700647 mBuffers[index].compBuffer = result;
648 }
649 if (c2buffer) {
650 *c2buffer = result;
651 }
652 return true;
653}
654
655bool BuffersArrayImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
656 for (size_t i = 0; i < mBuffers.size(); ++i) {
657 std::shared_ptr<C2Buffer> compBuffer =
658 mBuffers[i].compBuffer.lock();
659 if (!compBuffer) {
660 continue;
661 }
662 if (c2buffer == compBuffer) {
663 if (mBuffers[i].ownedByClient) {
664 // This should not happen.
665 ALOGD("[%s] codec released a buffer owned by client "
666 "(index %zu)", mName, i);
667 }
668 mBuffers[i].compBuffer.reset();
669 ALOGV("[%s] codec released buffer #%zu(array mode)", mName, i);
670 return true;
671 }
672 }
673 ALOGV("[%s] codec released an unknown buffer (array mode)", mName);
674 return false;
675}
676
677void BuffersArrayImpl::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
678 array->clear();
679 for (const Entry &entry : mBuffers) {
680 array->push(entry.clientBuffer);
681 }
682}
683
684void BuffersArrayImpl::flush() {
685 for (Entry &entry : mBuffers) {
686 entry.ownedByClient = false;
687 }
688}
689
690void BuffersArrayImpl::realloc(std::function<sp<Codec2Buffer>()> alloc) {
691 size_t size = mBuffers.size();
692 mBuffers.clear();
693 for (size_t i = 0; i < size; ++i) {
694 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
695 }
696}
697
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700698void BuffersArrayImpl::grow(
699 size_t newSize, std::function<sp<Codec2Buffer>()> alloc) {
700 CHECK_LT(mBuffers.size(), newSize);
701 while (mBuffers.size() < newSize) {
702 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
703 }
704}
705
Wonsik Kim0487b782020-10-28 11:45:50 -0700706size_t BuffersArrayImpl::numActiveSlots() const {
Wonsik Kim469c8342019-04-11 16:46:09 -0700707 return std::count_if(
708 mBuffers.begin(), mBuffers.end(),
709 [](const Entry &entry) {
Wonsik Kim0487b782020-10-28 11:45:50 -0700710 return entry.ownedByClient || !entry.compBuffer.expired();
Wonsik Kim469c8342019-04-11 16:46:09 -0700711 });
712}
713
Wonsik Kima39882b2019-06-20 16:13:56 -0700714size_t BuffersArrayImpl::arraySize() const {
715 return mBuffers.size();
716}
717
Wonsik Kim469c8342019-04-11 16:46:09 -0700718// InputBuffersArray
719
720void InputBuffersArray::initialize(
721 const FlexBuffersImpl &impl,
722 size_t minSize,
723 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700724 mAllocate = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -0700725 mImpl.initialize(impl, minSize, allocate);
726}
727
728void InputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
729 mImpl.getArray(array);
730}
731
732bool InputBuffersArray::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
733 sp<Codec2Buffer> c2Buffer;
734 status_t err = mImpl.grabBuffer(index, &c2Buffer);
735 if (err == OK) {
736 c2Buffer->setFormat(mFormat);
737 handleImageData(c2Buffer);
738 *buffer = c2Buffer;
739 return true;
740 }
741 return false;
742}
743
744bool InputBuffersArray::releaseBuffer(
745 const sp<MediaCodecBuffer> &buffer,
746 std::shared_ptr<C2Buffer> *c2buffer,
747 bool release) {
748 return mImpl.returnBuffer(buffer, c2buffer, release);
749}
750
751bool InputBuffersArray::expireComponentBuffer(
752 const std::shared_ptr<C2Buffer> &c2buffer) {
753 return mImpl.expireComponentBuffer(c2buffer);
754}
755
756void InputBuffersArray::flush() {
757 mImpl.flush();
758}
759
Wonsik Kim0487b782020-10-28 11:45:50 -0700760size_t InputBuffersArray::numActiveSlots() const {
761 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700762}
763
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700764sp<Codec2Buffer> InputBuffersArray::createNewBuffer() {
765 return mAllocate();
766}
767
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800768// SlotInputBuffers
769
770bool SlotInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
771 sp<Codec2Buffer> newBuffer = createNewBuffer();
772 *index = mImpl.assignSlot(newBuffer);
773 *buffer = newBuffer;
774 return true;
775}
776
777bool SlotInputBuffers::releaseBuffer(
778 const sp<MediaCodecBuffer> &buffer,
779 std::shared_ptr<C2Buffer> *c2buffer,
780 bool release) {
781 return mImpl.releaseSlot(buffer, c2buffer, release);
782}
783
784bool SlotInputBuffers::expireComponentBuffer(
785 const std::shared_ptr<C2Buffer> &c2buffer) {
786 return mImpl.expireComponentBuffer(c2buffer);
787}
788
789void SlotInputBuffers::flush() {
790 mImpl.flush();
791}
792
793std::unique_ptr<InputBuffers> SlotInputBuffers::toArrayMode(size_t) {
794 TRESPASS("Array mode should not be called at non-legacy mode");
795 return nullptr;
796}
797
Wonsik Kim0487b782020-10-28 11:45:50 -0700798size_t SlotInputBuffers::numActiveSlots() const {
799 return mImpl.numActiveSlots();
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800800}
801
802sp<Codec2Buffer> SlotInputBuffers::createNewBuffer() {
803 return new DummyContainerBuffer{mFormat, nullptr};
804}
805
Wonsik Kim469c8342019-04-11 16:46:09 -0700806// LinearInputBuffers
807
808bool LinearInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700809 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700810 if (newBuffer == nullptr) {
811 return false;
812 }
813 *index = mImpl.assignSlot(newBuffer);
814 *buffer = newBuffer;
815 return true;
816}
817
818bool LinearInputBuffers::releaseBuffer(
819 const sp<MediaCodecBuffer> &buffer,
820 std::shared_ptr<C2Buffer> *c2buffer,
821 bool release) {
822 return mImpl.releaseSlot(buffer, c2buffer, release);
823}
824
825bool LinearInputBuffers::expireComponentBuffer(
826 const std::shared_ptr<C2Buffer> &c2buffer) {
827 return mImpl.expireComponentBuffer(c2buffer);
828}
829
830void LinearInputBuffers::flush() {
831 // This is no-op by default unless we're in array mode where we need to keep
832 // track of the flushed work.
833 mImpl.flush();
834}
835
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700836std::unique_ptr<InputBuffers> LinearInputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700837 std::unique_ptr<InputBuffersArray> array(
838 new InputBuffersArray(mComponentName.c_str(), "1D-Input[N]"));
839 array->setPool(mPool);
840 array->setFormat(mFormat);
841 array->initialize(
842 mImpl,
843 size,
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700844 [pool = mPool, format = mFormat] () -> sp<Codec2Buffer> {
845 return Alloc(pool, format);
846 });
Wonsik Kim469c8342019-04-11 16:46:09 -0700847 return std::move(array);
848}
849
Wonsik Kim0487b782020-10-28 11:45:50 -0700850size_t LinearInputBuffers::numActiveSlots() const {
851 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700852}
853
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700854// static
855sp<Codec2Buffer> LinearInputBuffers::Alloc(
856 const std::shared_ptr<C2BlockPool> &pool, const sp<AMessage> &format) {
857 int32_t capacity = kLinearBufferSize;
858 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
859 if ((size_t)capacity > kMaxLinearBufferSize) {
860 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
861 capacity = kMaxLinearBufferSize;
862 }
863
Wonsik Kim666604a2020-05-14 16:57:49 -0700864 int64_t usageValue = 0;
865 (void)format->findInt64("android._C2MemoryUsage", &usageValue);
866 C2MemoryUsage usage{usageValue | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE};
Wonsik Kim469c8342019-04-11 16:46:09 -0700867 std::shared_ptr<C2LinearBlock> block;
868
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700869 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700870 if (err != C2_OK) {
871 return nullptr;
872 }
873
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700874 return LinearBlockBuffer::Allocate(format, block);
875}
876
877sp<Codec2Buffer> LinearInputBuffers::createNewBuffer() {
878 return Alloc(mPool, mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -0700879}
880
881// EncryptedLinearInputBuffers
882
883EncryptedLinearInputBuffers::EncryptedLinearInputBuffers(
884 bool secure,
885 const sp<MemoryDealer> &dealer,
886 const sp<ICrypto> &crypto,
887 int32_t heapSeqNum,
888 size_t capacity,
889 size_t numInputSlots,
890 const char *componentName, const char *name)
891 : LinearInputBuffers(componentName, name),
892 mUsage({0, 0}),
893 mDealer(dealer),
894 mCrypto(crypto),
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700895 mMemoryVector(new std::vector<Entry>){
Wonsik Kim469c8342019-04-11 16:46:09 -0700896 if (secure) {
897 mUsage = { C2MemoryUsage::READ_PROTECTED, 0 };
898 } else {
899 mUsage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
900 }
901 for (size_t i = 0; i < numInputSlots; ++i) {
902 sp<IMemory> memory = mDealer->allocate(capacity);
903 if (memory == nullptr) {
904 ALOGD("[%s] Failed to allocate memory from dealer: only %zu slots allocated",
905 mName, i);
906 break;
907 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700908 mMemoryVector->push_back({std::weak_ptr<C2LinearBlock>(), memory, heapSeqNum});
Wonsik Kim469c8342019-04-11 16:46:09 -0700909 }
910}
911
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700912std::unique_ptr<InputBuffers> EncryptedLinearInputBuffers::toArrayMode(size_t size) {
913 std::unique_ptr<InputBuffersArray> array(
914 new InputBuffersArray(mComponentName.c_str(), "1D-EncryptedInput[N]"));
915 array->setPool(mPool);
916 array->setFormat(mFormat);
917 array->initialize(
918 mImpl,
919 size,
920 [pool = mPool,
921 format = mFormat,
922 usage = mUsage,
923 memoryVector = mMemoryVector] () -> sp<Codec2Buffer> {
924 return Alloc(pool, format, usage, memoryVector);
925 });
926 return std::move(array);
927}
928
929
930// static
931sp<Codec2Buffer> EncryptedLinearInputBuffers::Alloc(
932 const std::shared_ptr<C2BlockPool> &pool,
933 const sp<AMessage> &format,
934 C2MemoryUsage usage,
935 const std::shared_ptr<std::vector<EncryptedLinearInputBuffers::Entry>> &memoryVector) {
936 int32_t capacity = kLinearBufferSize;
937 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
938 if ((size_t)capacity > kMaxLinearBufferSize) {
939 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
940 capacity = kMaxLinearBufferSize;
941 }
942
Wonsik Kim469c8342019-04-11 16:46:09 -0700943 sp<IMemory> memory;
944 size_t slot = 0;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700945 int32_t heapSeqNum = -1;
946 for (; slot < memoryVector->size(); ++slot) {
947 if (memoryVector->at(slot).block.expired()) {
948 memory = memoryVector->at(slot).memory;
949 heapSeqNum = memoryVector->at(slot).heapSeqNum;
Wonsik Kim469c8342019-04-11 16:46:09 -0700950 break;
951 }
952 }
953 if (memory == nullptr) {
954 return nullptr;
955 }
956
David Stevens94b608f2021-07-29 15:04:14 +0900957 int64_t usageValue = 0;
958 (void)format->findInt64("android._C2MemoryUsage", &usageValue);
959 usage = C2MemoryUsage(usage.expected | usageValue);
960
Wonsik Kim469c8342019-04-11 16:46:09 -0700961 std::shared_ptr<C2LinearBlock> block;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700962 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700963 if (err != C2_OK || block == nullptr) {
964 return nullptr;
965 }
966
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700967 memoryVector->at(slot).block = block;
968 return new EncryptedLinearBlockBuffer(format, block, memory, heapSeqNum);
969}
970
971sp<Codec2Buffer> EncryptedLinearInputBuffers::createNewBuffer() {
972 // TODO: android_2020
973 return nullptr;
Wonsik Kim469c8342019-04-11 16:46:09 -0700974}
975
976// GraphicMetadataInputBuffers
977
978GraphicMetadataInputBuffers::GraphicMetadataInputBuffers(
979 const char *componentName, const char *name)
980 : InputBuffers(componentName, name),
981 mImpl(mName),
982 mStore(GetCodec2PlatformAllocatorStore()) { }
983
984bool GraphicMetadataInputBuffers::requestNewBuffer(
985 size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700986 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700987 if (newBuffer == nullptr) {
988 return false;
989 }
990 *index = mImpl.assignSlot(newBuffer);
991 *buffer = newBuffer;
992 return true;
993}
994
995bool GraphicMetadataInputBuffers::releaseBuffer(
996 const sp<MediaCodecBuffer> &buffer,
997 std::shared_ptr<C2Buffer> *c2buffer,
998 bool release) {
999 return mImpl.releaseSlot(buffer, c2buffer, release);
1000}
1001
1002bool GraphicMetadataInputBuffers::expireComponentBuffer(
1003 const std::shared_ptr<C2Buffer> &c2buffer) {
1004 return mImpl.expireComponentBuffer(c2buffer);
1005}
1006
1007void GraphicMetadataInputBuffers::flush() {
1008 // This is no-op by default unless we're in array mode where we need to keep
1009 // track of the flushed work.
1010}
1011
1012std::unique_ptr<InputBuffers> GraphicMetadataInputBuffers::toArrayMode(
1013 size_t size) {
1014 std::shared_ptr<C2Allocator> alloc;
1015 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
1016 if (err != C2_OK) {
1017 return nullptr;
1018 }
1019 std::unique_ptr<InputBuffersArray> array(
1020 new InputBuffersArray(mComponentName.c_str(), "2D-MetaInput[N]"));
1021 array->setPool(mPool);
1022 array->setFormat(mFormat);
1023 array->initialize(
1024 mImpl,
1025 size,
1026 [format = mFormat, alloc]() -> sp<Codec2Buffer> {
1027 return new GraphicMetadataBuffer(format, alloc);
1028 });
1029 return std::move(array);
1030}
1031
Wonsik Kim0487b782020-10-28 11:45:50 -07001032size_t GraphicMetadataInputBuffers::numActiveSlots() const {
1033 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001034}
1035
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001036sp<Codec2Buffer> GraphicMetadataInputBuffers::createNewBuffer() {
1037 std::shared_ptr<C2Allocator> alloc;
1038 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
1039 if (err != C2_OK) {
1040 return nullptr;
1041 }
1042 return new GraphicMetadataBuffer(mFormat, alloc);
1043}
1044
Wonsik Kim469c8342019-04-11 16:46:09 -07001045// GraphicInputBuffers
1046
1047GraphicInputBuffers::GraphicInputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -07001048 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -07001049 : InputBuffers(componentName, name),
1050 mImpl(mName),
Songyue Han1e6769b2023-08-30 18:09:27 +00001051 mLocalBufferPool(LocalBufferPool::Create()),
1052 mPixelFormat(PIXEL_FORMAT_UNKNOWN) { }
Wonsik Kim469c8342019-04-11 16:46:09 -07001053
1054bool GraphicInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001055 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -07001056 if (newBuffer == nullptr) {
1057 return false;
1058 }
1059 *index = mImpl.assignSlot(newBuffer);
1060 handleImageData(newBuffer);
1061 *buffer = newBuffer;
1062 return true;
1063}
1064
1065bool GraphicInputBuffers::releaseBuffer(
1066 const sp<MediaCodecBuffer> &buffer,
1067 std::shared_ptr<C2Buffer> *c2buffer,
1068 bool release) {
1069 return mImpl.releaseSlot(buffer, c2buffer, release);
1070}
1071
1072bool GraphicInputBuffers::expireComponentBuffer(
1073 const std::shared_ptr<C2Buffer> &c2buffer) {
1074 return mImpl.expireComponentBuffer(c2buffer);
1075}
1076
1077void GraphicInputBuffers::flush() {
1078 // This is no-op by default unless we're in array mode where we need to keep
1079 // track of the flushed work.
1080}
1081
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001082static uint32_t extractPixelFormat(const sp<AMessage> &format) {
1083 int32_t frameworkColorFormat = 0;
1084 if (!format->findInt32("android._color-format", &frameworkColorFormat)) {
1085 return PIXEL_FORMAT_UNKNOWN;
1086 }
1087 uint32_t pixelFormat = PIXEL_FORMAT_UNKNOWN;
1088 if (C2Mapper::mapPixelFormatFrameworkToCodec(frameworkColorFormat, &pixelFormat)) {
1089 return pixelFormat;
1090 }
1091 return PIXEL_FORMAT_UNKNOWN;
1092}
1093
Wonsik Kim469c8342019-04-11 16:46:09 -07001094std::unique_ptr<InputBuffers> GraphicInputBuffers::toArrayMode(size_t size) {
1095 std::unique_ptr<InputBuffersArray> array(
1096 new InputBuffersArray(mComponentName.c_str(), "2D-BB-Input[N]"));
1097 array->setPool(mPool);
1098 array->setFormat(mFormat);
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001099 uint32_t pixelFormat = extractPixelFormat(mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -07001100 array->initialize(
1101 mImpl,
1102 size,
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001103 [pool = mPool, format = mFormat, lbp = mLocalBufferPool, pixelFormat]()
1104 -> sp<Codec2Buffer> {
Wonsik Kim469c8342019-04-11 16:46:09 -07001105 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
David Stevens94b608f2021-07-29 15:04:14 +09001106 return AllocateInputGraphicBuffer(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001107 pool, format, pixelFormat, usage, lbp);
Wonsik Kim469c8342019-04-11 16:46:09 -07001108 });
1109 return std::move(array);
1110}
1111
Wonsik Kim0487b782020-10-28 11:45:50 -07001112size_t GraphicInputBuffers::numActiveSlots() const {
1113 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001114}
1115
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001116sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
David Stevens94b608f2021-07-29 15:04:14 +09001117 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
Songyue Han1e6769b2023-08-30 18:09:27 +00001118 mPixelFormat = extractPixelFormat(mFormat);
David Stevens94b608f2021-07-29 15:04:14 +09001119 return AllocateInputGraphicBuffer(
Songyue Han1e6769b2023-08-30 18:09:27 +00001120 mPool, mFormat, mPixelFormat, usage, mLocalBufferPool);
1121}
1122
1123uint32_t GraphicInputBuffers::getPixelFormatIfApplicable() { return mPixelFormat; }
1124
1125bool GraphicInputBuffers::resetPixelFormatIfApplicable() {
1126 mPixelFormat = PIXEL_FORMAT_UNKNOWN;
1127 return true;
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001128}
1129
Wonsik Kim469c8342019-04-11 16:46:09 -07001130// OutputBuffersArray
1131
1132void OutputBuffersArray::initialize(
1133 const FlexBuffersImpl &impl,
1134 size_t minSize,
1135 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001136 mAlloc = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -07001137 mImpl.initialize(impl, minSize, allocate);
1138}
1139
1140status_t OutputBuffersArray::registerBuffer(
1141 const std::shared_ptr<C2Buffer> &buffer,
1142 size_t *index,
1143 sp<MediaCodecBuffer> *clientBuffer) {
1144 sp<Codec2Buffer> c2Buffer;
1145 status_t err = mImpl.grabBuffer(
1146 index,
1147 &c2Buffer,
1148 [buffer](const sp<Codec2Buffer> &clientBuffer) {
1149 return clientBuffer->canCopy(buffer);
1150 });
1151 if (err == WOULD_BLOCK) {
1152 ALOGV("[%s] buffers temporarily not available", mName);
1153 return err;
1154 } else if (err != OK) {
1155 ALOGD("[%s] grabBuffer failed: %d", mName, err);
1156 return err;
1157 }
1158 c2Buffer->setFormat(mFormat);
Wonsik Kim6f23cfc2021-09-24 05:45:52 -07001159 if (!convert(buffer, &c2Buffer) && !c2Buffer->copy(buffer)) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001160 ALOGD("[%s] copy buffer failed", mName);
1161 return WOULD_BLOCK;
1162 }
1163 submit(c2Buffer);
1164 handleImageData(c2Buffer);
1165 *clientBuffer = c2Buffer;
1166 ALOGV("[%s] grabbed buffer %zu", mName, *index);
1167 return OK;
1168}
1169
1170status_t OutputBuffersArray::registerCsd(
1171 const C2StreamInitDataInfo::output *csd,
1172 size_t *index,
1173 sp<MediaCodecBuffer> *clientBuffer) {
1174 sp<Codec2Buffer> c2Buffer;
1175 status_t err = mImpl.grabBuffer(
1176 index,
1177 &c2Buffer,
1178 [csd](const sp<Codec2Buffer> &clientBuffer) {
1179 return clientBuffer->base() != nullptr
1180 && clientBuffer->capacity() >= csd->flexCount();
1181 });
1182 if (err != OK) {
1183 return err;
1184 }
1185 memcpy(c2Buffer->base(), csd->m.value, csd->flexCount());
1186 c2Buffer->setRange(0, csd->flexCount());
1187 c2Buffer->setFormat(mFormat);
1188 *clientBuffer = c2Buffer;
1189 return OK;
1190}
1191
1192bool OutputBuffersArray::releaseBuffer(
1193 const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) {
1194 return mImpl.returnBuffer(buffer, c2buffer, true);
1195}
1196
1197void OutputBuffersArray::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1198 (void)flushedWork;
1199 mImpl.flush();
1200 if (mSkipCutBuffer != nullptr) {
1201 mSkipCutBuffer->clear();
1202 }
1203}
1204
1205void OutputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
1206 mImpl.getArray(array);
1207}
1208
Wonsik Kim0487b782020-10-28 11:45:50 -07001209size_t OutputBuffersArray::numActiveSlots() const {
1210 return mImpl.numActiveSlots();
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001211}
1212
Wonsik Kim469c8342019-04-11 16:46:09 -07001213void OutputBuffersArray::realloc(const std::shared_ptr<C2Buffer> &c2buffer) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001214 switch (c2buffer->data().type()) {
1215 case C2BufferData::LINEAR: {
1216 uint32_t size = kLinearBufferSize;
Nick Desaulniersd09eaea2019-10-07 20:19:39 -07001217 const std::vector<C2ConstLinearBlock> &linear_blocks = c2buffer->data().linearBlocks();
1218 const uint32_t block_size = linear_blocks.front().size();
1219 if (block_size < kMaxLinearBufferSize / 2) {
1220 size = block_size * 2;
Wonsik Kim469c8342019-04-11 16:46:09 -07001221 } else {
1222 size = kMaxLinearBufferSize;
1223 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001224 mAlloc = [format = mFormat, size] {
Wonsik Kim469c8342019-04-11 16:46:09 -07001225 return new LocalLinearBuffer(format, new ABuffer(size));
1226 };
Wonsik Kima39882b2019-06-20 16:13:56 -07001227 ALOGD("[%s] reallocating with linear buffer of size %u", mName, size);
Wonsik Kim469c8342019-04-11 16:46:09 -07001228 break;
1229 }
1230
Wonsik Kima39882b2019-06-20 16:13:56 -07001231 case C2BufferData::GRAPHIC: {
1232 // This is only called for RawGraphicOutputBuffers.
1233 mAlloc = [format = mFormat,
Wonsik Kim41d83432020-04-27 16:40:49 -07001234 lbp = LocalBufferPool::Create()] {
Wonsik Kima39882b2019-06-20 16:13:56 -07001235 return ConstGraphicBlockBuffer::AllocateEmpty(
1236 format,
1237 [lbp](size_t capacity) {
1238 return lbp->newBuffer(capacity);
1239 });
1240 };
1241 ALOGD("[%s] reallocating with graphic buffer: format = %s",
1242 mName, mFormat->debugString().c_str());
1243 break;
1244 }
Wonsik Kim469c8342019-04-11 16:46:09 -07001245
1246 case C2BufferData::INVALID: [[fallthrough]];
1247 case C2BufferData::LINEAR_CHUNKS: [[fallthrough]];
1248 case C2BufferData::GRAPHIC_CHUNKS: [[fallthrough]];
1249 default:
1250 ALOGD("Unsupported type: %d", (int)c2buffer->data().type());
1251 return;
1252 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001253 mImpl.realloc(mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -07001254}
1255
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001256void OutputBuffersArray::grow(size_t newSize) {
1257 mImpl.grow(newSize, mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -07001258}
1259
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001260void OutputBuffersArray::transferFrom(OutputBuffers* source) {
1261 mFormat = source->mFormat;
1262 mSkipCutBuffer = source->mSkipCutBuffer;
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001263 mPending = std::move(source->mPending);
1264 mReorderStash = std::move(source->mReorderStash);
1265 mDepth = source->mDepth;
1266 mKey = source->mKey;
1267}
1268
Wonsik Kim469c8342019-04-11 16:46:09 -07001269// FlexOutputBuffers
1270
1271status_t FlexOutputBuffers::registerBuffer(
1272 const std::shared_ptr<C2Buffer> &buffer,
1273 size_t *index,
1274 sp<MediaCodecBuffer> *clientBuffer) {
Wonsik Kim6f23cfc2021-09-24 05:45:52 -07001275 sp<Codec2Buffer> newBuffer;
1276 if (!convert(buffer, &newBuffer)) {
1277 newBuffer = wrap(buffer);
1278 if (newBuffer == nullptr) {
1279 return NO_MEMORY;
1280 }
Wonsik Kim360ba0a2022-05-23 15:38:21 -07001281 newBuffer->setFormat(mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -07001282 }
Wonsik Kim469c8342019-04-11 16:46:09 -07001283 *index = mImpl.assignSlot(newBuffer);
1284 handleImageData(newBuffer);
1285 *clientBuffer = newBuffer;
Songyue Han1e6769b2023-08-30 18:09:27 +00001286
1287 extractPixelFormatFromC2Buffer(buffer);
Wonsik Kim469c8342019-04-11 16:46:09 -07001288 ALOGV("[%s] registered buffer %zu", mName, *index);
1289 return OK;
1290}
1291
1292status_t FlexOutputBuffers::registerCsd(
1293 const C2StreamInitDataInfo::output *csd,
1294 size_t *index,
1295 sp<MediaCodecBuffer> *clientBuffer) {
1296 sp<Codec2Buffer> newBuffer = new LocalLinearBuffer(
1297 mFormat, ABuffer::CreateAsCopy(csd->m.value, csd->flexCount()));
1298 *index = mImpl.assignSlot(newBuffer);
1299 *clientBuffer = newBuffer;
1300 return OK;
1301}
1302
1303bool FlexOutputBuffers::releaseBuffer(
1304 const sp<MediaCodecBuffer> &buffer,
1305 std::shared_ptr<C2Buffer> *c2buffer) {
1306 return mImpl.releaseSlot(buffer, c2buffer, true);
1307}
1308
1309void FlexOutputBuffers::flush(
1310 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1311 (void) flushedWork;
1312 // This is no-op by default unless we're in array mode where we need to keep
1313 // track of the flushed work.
1314}
1315
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001316std::unique_ptr<OutputBuffersArray> FlexOutputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001317 std::unique_ptr<OutputBuffersArray> array(new OutputBuffersArray(mComponentName.c_str()));
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001318 array->transferFrom(this);
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001319 std::function<sp<Codec2Buffer>()> alloc = getAlloc();
1320 array->initialize(mImpl, size, alloc);
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001321 return array;
Wonsik Kim469c8342019-04-11 16:46:09 -07001322}
1323
Wonsik Kim0487b782020-10-28 11:45:50 -07001324size_t FlexOutputBuffers::numActiveSlots() const {
1325 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001326}
1327
Songyue Han1e6769b2023-08-30 18:09:27 +00001328bool FlexOutputBuffers::extractPixelFormatFromC2Buffer(const std::shared_ptr<C2Buffer> &buffer) {
1329 if (buffer == nullptr) {
1330 return false;
1331 }
1332 const C2BufferData &data = buffer->data();
1333 // only extract the first pixel format in a metric session.
1334 if (mPixelFormat != PIXEL_FORMAT_UNKNOWN || data.type() != C2BufferData::GRAPHIC
1335 || data.graphicBlocks().empty()) {
1336 return false;
1337 }
1338 const C2Handle *const handle = data.graphicBlocks().front().handle();
1339 uint32_t pf = ExtractFormatFromCodec2GrallocHandle(handle);
1340 if (pf == PIXEL_FORMAT_UNKNOWN) {
1341 return false;
1342 }
1343 mPixelFormat = pf;
1344 return true;
1345}
1346
1347bool FlexOutputBuffers::resetPixelFormatIfApplicable() {
1348 mPixelFormat = PIXEL_FORMAT_UNKNOWN;
1349 return true;
1350}
1351
1352uint32_t FlexOutputBuffers::getPixelFormatIfApplicable() { return mPixelFormat; }
1353
Wonsik Kim469c8342019-04-11 16:46:09 -07001354// LinearOutputBuffers
1355
1356void LinearOutputBuffers::flush(
1357 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1358 if (mSkipCutBuffer != nullptr) {
1359 mSkipCutBuffer->clear();
1360 }
1361 FlexOutputBuffers::flush(flushedWork);
1362}
1363
1364sp<Codec2Buffer> LinearOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1365 if (buffer == nullptr) {
1366 ALOGV("[%s] using a dummy buffer", mName);
1367 return new LocalLinearBuffer(mFormat, new ABuffer(0));
1368 }
1369 if (buffer->data().type() != C2BufferData::LINEAR) {
1370 ALOGV("[%s] non-linear buffer %d", mName, buffer->data().type());
1371 // We expect linear output buffers from the component.
1372 return nullptr;
1373 }
1374 if (buffer->data().linearBlocks().size() != 1u) {
1375 ALOGV("[%s] no linear buffers", mName);
1376 // We expect one and only one linear block from the component.
1377 return nullptr;
1378 }
1379 sp<Codec2Buffer> clientBuffer = ConstLinearBlockBuffer::Allocate(mFormat, buffer);
1380 if (clientBuffer == nullptr) {
1381 ALOGD("[%s] ConstLinearBlockBuffer::Allocate failed", mName);
1382 return nullptr;
1383 }
1384 submit(clientBuffer);
1385 return clientBuffer;
1386}
1387
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001388std::function<sp<Codec2Buffer>()> LinearOutputBuffers::getAlloc() {
1389 return [format = mFormat]{
1390 // TODO: proper max output size
1391 return new LocalLinearBuffer(format, new ABuffer(kLinearBufferSize));
1392 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001393}
1394
1395// GraphicOutputBuffers
1396
1397sp<Codec2Buffer> GraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1398 return new DummyContainerBuffer(mFormat, buffer);
1399}
1400
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001401std::function<sp<Codec2Buffer>()> GraphicOutputBuffers::getAlloc() {
1402 return [format = mFormat]{
1403 return new DummyContainerBuffer(format);
1404 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001405}
1406
1407// RawGraphicOutputBuffers
1408
1409RawGraphicOutputBuffers::RawGraphicOutputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -07001410 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -07001411 : FlexOutputBuffers(componentName, name),
Wonsik Kim41d83432020-04-27 16:40:49 -07001412 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -07001413
1414sp<Codec2Buffer> RawGraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1415 if (buffer == nullptr) {
Wonsik Kim6f116902021-07-14 08:58:07 -07001416 return new Codec2Buffer(mFormat, new ABuffer(nullptr, 0));
Wonsik Kim469c8342019-04-11 16:46:09 -07001417 } else {
1418 return ConstGraphicBlockBuffer::Allocate(
1419 mFormat,
1420 buffer,
1421 [lbp = mLocalBufferPool](size_t capacity) {
1422 return lbp->newBuffer(capacity);
1423 });
1424 }
1425}
1426
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001427std::function<sp<Codec2Buffer>()> RawGraphicOutputBuffers::getAlloc() {
1428 return [format = mFormat, lbp = mLocalBufferPool]{
1429 return ConstGraphicBlockBuffer::AllocateEmpty(
1430 format,
1431 [lbp](size_t capacity) {
1432 return lbp->newBuffer(capacity);
1433 });
1434 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001435}
1436
1437} // namespace android