blob: cfa89cf413670759cbb1e2bf01ed7f4db9d24712 [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
21#include <C2PlatformSupport.h>
22
23#include <media/stagefright/foundation/ADebug.h>
Pawin Vongmasa9b906982020-04-11 05:07:15 -070024#include <media/stagefright/MediaCodec.h>
Wonsik Kim469c8342019-04-11 16:46:09 -070025#include <media/stagefright/MediaCodecConstants.h>
Wonsik Kim155d5cb2019-10-09 12:49:49 -070026#include <media/stagefright/SkipCutBuffer.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070027#include <mediadrm/ICrypto.h>
Wonsik Kim469c8342019-04-11 16:46:09 -070028
29#include "CCodecBuffers.h"
Wonsik Kimd79ee1f2020-08-27 17:41:56 -070030#include "Codec2Mapper.h"
Wonsik Kim469c8342019-04-11 16:46:09 -070031
32namespace android {
33
34namespace {
35
36sp<GraphicBlockBuffer> AllocateGraphicBuffer(
37 const std::shared_ptr<C2BlockPool> &pool,
38 const sp<AMessage> &format,
39 uint32_t pixelFormat,
40 const C2MemoryUsage &usage,
41 const std::shared_ptr<LocalBufferPool> &localBufferPool) {
42 int32_t width, height;
43 if (!format->findInt32("width", &width) || !format->findInt32("height", &height)) {
44 ALOGD("format lacks width or height");
45 return nullptr;
46 }
47
48 std::shared_ptr<C2GraphicBlock> block;
49 c2_status_t err = pool->fetchGraphicBlock(
50 width, height, pixelFormat, usage, &block);
51 if (err != C2_OK) {
52 ALOGD("fetch graphic block failed: %d", err);
53 return nullptr;
54 }
55
56 return GraphicBlockBuffer::Allocate(
57 format,
58 block,
59 [localBufferPool](size_t capacity) {
60 return localBufferPool->newBuffer(capacity);
61 });
62}
63
64} // namespace
65
66// CCodecBuffers
67
68void CCodecBuffers::setFormat(const sp<AMessage> &format) {
69 CHECK(format != nullptr);
70 mFormat = format;
71}
72
73sp<AMessage> CCodecBuffers::dupFormat() {
74 return mFormat != nullptr ? mFormat->dup() : nullptr;
75}
76
77void CCodecBuffers::handleImageData(const sp<Codec2Buffer> &buffer) {
78 sp<ABuffer> imageDataCandidate = buffer->getImageData();
79 if (imageDataCandidate == nullptr) {
Wonsik Kim4a3c0462021-03-09 15:45:05 -080080 if (mFormatWithImageData) {
81 // We previously sent the format with image data, so use the same format.
82 buffer->setFormat(mFormatWithImageData);
83 }
Wonsik Kim469c8342019-04-11 16:46:09 -070084 return;
85 }
Wonsik Kim4a3c0462021-03-09 15:45:05 -080086 if (!mLastImageData
87 || imageDataCandidate->size() != mLastImageData->size()
88 || memcmp(imageDataCandidate->data(),
89 mLastImageData->data(),
90 mLastImageData->size()) != 0) {
Wonsik Kim469c8342019-04-11 16:46:09 -070091 ALOGD("[%s] updating image-data", mName);
Wonsik Kim4a3c0462021-03-09 15:45:05 -080092 mFormatWithImageData = dupFormat();
93 mLastImageData = imageDataCandidate;
94 mFormatWithImageData->setBuffer("image-data", imageDataCandidate);
Wonsik Kim469c8342019-04-11 16:46:09 -070095 MediaImage2 *img = (MediaImage2*)imageDataCandidate->data();
96 if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
97 int32_t stride = img->mPlane[0].mRowInc;
Wonsik Kim4a3c0462021-03-09 15:45:05 -080098 mFormatWithImageData->setInt32(KEY_STRIDE, stride);
Wonsik Kim469c8342019-04-11 16:46:09 -070099 ALOGD("[%s] updating stride = %d", mName, stride);
100 if (img->mNumPlanes > 1 && stride > 0) {
Taehwan Kimfd9b8092020-09-17 12:26:40 +0900101 int64_t offsetDelta =
102 (int64_t)img->mPlane[1].mOffset - (int64_t)img->mPlane[0].mOffset;
103 int32_t vstride = int32_t(offsetDelta / stride);
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800104 mFormatWithImageData->setInt32(KEY_SLICE_HEIGHT, vstride);
Wonsik Kim469c8342019-04-11 16:46:09 -0700105 ALOGD("[%s] updating vstride = %d", mName, vstride);
Wonsik Kim2eb06312020-12-03 11:07:58 -0800106 buffer->setRange(
107 img->mPlane[0].mOffset,
108 buffer->size() - img->mPlane[0].mOffset);
Wonsik Kim469c8342019-04-11 16:46:09 -0700109 }
110 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700111 }
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800112 buffer->setFormat(mFormatWithImageData);
Wonsik Kim469c8342019-04-11 16:46:09 -0700113}
114
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700115// InputBuffers
116
117sp<Codec2Buffer> InputBuffers::cloneAndReleaseBuffer(const sp<MediaCodecBuffer> &buffer) {
118 sp<Codec2Buffer> copy = createNewBuffer();
119 if (copy == nullptr) {
120 return nullptr;
121 }
122 std::shared_ptr<C2Buffer> c2buffer;
123 if (!releaseBuffer(buffer, &c2buffer, true)) {
124 return nullptr;
125 }
126 if (!copy->canCopy(c2buffer)) {
127 return nullptr;
128 }
129 if (!copy->copy(c2buffer)) {
130 return nullptr;
131 }
Wonsik Kimfb5ca492021-08-11 14:18:19 -0700132 copy->meta()->extend(buffer->meta());
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700133 return copy;
134}
135
Wonsik Kim469c8342019-04-11 16:46:09 -0700136// OutputBuffers
137
Wonsik Kim41d83432020-04-27 16:40:49 -0700138OutputBuffers::OutputBuffers(const char *componentName, const char *name)
139 : CCodecBuffers(componentName, name) { }
140
141OutputBuffers::~OutputBuffers() = default;
142
Wonsik Kim469c8342019-04-11 16:46:09 -0700143void OutputBuffers::initSkipCutBuffer(
144 int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount) {
145 CHECK(mSkipCutBuffer == nullptr);
146 mDelay = delay;
147 mPadding = padding;
148 mSampleRate = sampleRate;
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700149 mChannelCount = channelCount;
150 setSkipCutBuffer(delay, padding);
Wonsik Kim469c8342019-04-11 16:46:09 -0700151}
152
153void OutputBuffers::updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount) {
154 if (mSkipCutBuffer == nullptr) {
155 return;
156 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700157 if (mSampleRate == sampleRate && mChannelCount == channelCount) {
158 return;
159 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700160 int32_t delay = mDelay;
161 int32_t padding = mPadding;
162 if (sampleRate != mSampleRate) {
163 delay = ((int64_t)delay * sampleRate) / mSampleRate;
164 padding = ((int64_t)padding * sampleRate) / mSampleRate;
165 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700166 mSampleRate = sampleRate;
167 mChannelCount = channelCount;
168 setSkipCutBuffer(delay, padding);
Wonsik Kim469c8342019-04-11 16:46:09 -0700169}
170
Wonsik Kim970bf0b2020-11-10 11:54:15 -0800171void OutputBuffers::updateSkipCutBuffer(const sp<AMessage> &format) {
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700172 AString mediaType;
173 if (format->findString(KEY_MIME, &mediaType)
174 && mediaType == MIMETYPE_AUDIO_RAW) {
175 int32_t channelCount;
176 int32_t sampleRate;
177 if (format->findInt32(KEY_CHANNEL_COUNT, &channelCount)
178 && format->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
179 updateSkipCutBuffer(sampleRate, channelCount);
180 }
181 }
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700182}
183
Wonsik Kim469c8342019-04-11 16:46:09 -0700184void OutputBuffers::submit(const sp<MediaCodecBuffer> &buffer) {
185 if (mSkipCutBuffer != nullptr) {
186 mSkipCutBuffer->submit(buffer);
187 }
188}
189
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700190void OutputBuffers::setSkipCutBuffer(int32_t skip, int32_t cut) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700191 if (mSkipCutBuffer != nullptr) {
192 size_t prevSize = mSkipCutBuffer->size();
193 if (prevSize != 0u) {
194 ALOGD("[%s] Replacing SkipCutBuffer holding %zu bytes", mName, prevSize);
195 }
196 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700197 mSkipCutBuffer = new SkipCutBuffer(skip, cut, mChannelCount);
Wonsik Kim469c8342019-04-11 16:46:09 -0700198}
199
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700200void OutputBuffers::clearStash() {
201 mPending.clear();
202 mReorderStash.clear();
203 mDepth = 0;
204 mKey = C2Config::ORDINAL;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700205}
206
207void OutputBuffers::flushStash() {
208 for (StashEntry& e : mPending) {
209 e.notify = false;
210 }
211 for (StashEntry& e : mReorderStash) {
212 e.notify = false;
213 }
214}
215
216uint32_t OutputBuffers::getReorderDepth() const {
217 return mDepth;
218}
219
220void OutputBuffers::setReorderDepth(uint32_t depth) {
221 mPending.splice(mPending.end(), mReorderStash);
222 mDepth = depth;
223}
224
225void OutputBuffers::setReorderKey(C2Config::ordinal_key_t key) {
226 mPending.splice(mPending.end(), mReorderStash);
227 mKey = key;
228}
229
230void OutputBuffers::pushToStash(
231 const std::shared_ptr<C2Buffer>& buffer,
232 bool notify,
233 int64_t timestamp,
234 int32_t flags,
235 const sp<AMessage>& format,
236 const C2WorkOrdinalStruct& ordinal) {
237 bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;
238 if (!buffer && eos) {
239 // TRICKY: we may be violating ordering of the stash here. Because we
240 // don't expect any more emplace() calls after this, the ordering should
241 // not matter.
242 mReorderStash.emplace_back(
243 buffer, notify, timestamp, flags, format, ordinal);
244 } else {
245 flags = flags & ~MediaCodec::BUFFER_FLAG_EOS;
246 auto it = mReorderStash.begin();
247 for (; it != mReorderStash.end(); ++it) {
248 if (less(ordinal, it->ordinal)) {
249 break;
250 }
251 }
252 mReorderStash.emplace(it,
253 buffer, notify, timestamp, flags, format, ordinal);
254 if (eos) {
255 mReorderStash.back().flags =
256 mReorderStash.back().flags | MediaCodec::BUFFER_FLAG_EOS;
257 }
258 }
259 while (!mReorderStash.empty() && mReorderStash.size() > mDepth) {
260 mPending.push_back(mReorderStash.front());
261 mReorderStash.pop_front();
262 }
263 ALOGV("[%s] %s: pushToStash -- pending size = %zu", mName, __func__, mPending.size());
264}
265
266OutputBuffers::BufferAction OutputBuffers::popFromStashAndRegister(
267 std::shared_ptr<C2Buffer>* c2Buffer,
268 size_t* index,
269 sp<MediaCodecBuffer>* outBuffer) {
270 if (mPending.empty()) {
271 return SKIP;
272 }
273
274 // Retrieve the first entry.
275 StashEntry &entry = mPending.front();
276
277 *c2Buffer = entry.buffer;
278 sp<AMessage> outputFormat = entry.format;
279
Wonsik Kim970bf0b2020-11-10 11:54:15 -0800280 if (entry.notify && mFormat != outputFormat) {
281 updateSkipCutBuffer(outputFormat);
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800282 // Trigger image data processing to the new format
283 mLastImageData.clear();
Wonsik Kim970bf0b2020-11-10 11:54:15 -0800284 ALOGV("[%s] popFromStashAndRegister: output format reference changed: %p -> %p",
285 mName, mFormat.get(), outputFormat.get());
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800286 ALOGD("[%s] popFromStashAndRegister: at %lldus, output format changed to %s",
287 mName, (long long)entry.timestamp, outputFormat->debugString().c_str());
Wonsik Kim970bf0b2020-11-10 11:54:15 -0800288 setFormat(outputFormat);
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700289 }
290
291 // Flushing mReorderStash because no other buffers should come after output
292 // EOS.
293 if (entry.flags & MediaCodec::BUFFER_FLAG_EOS) {
294 // Flush reorder stash
295 setReorderDepth(0);
296 }
297
298 if (!entry.notify) {
299 mPending.pop_front();
300 return DISCARD;
301 }
302
303 // Try to register the buffer.
304 status_t err = registerBuffer(*c2Buffer, index, outBuffer);
305 if (err != OK) {
306 if (err != WOULD_BLOCK) {
307 return REALLOCATE;
308 }
309 return RETRY;
310 }
311
312 // Append information from the front stash entry to outBuffer.
313 (*outBuffer)->meta()->setInt64("timeUs", entry.timestamp);
314 (*outBuffer)->meta()->setInt32("flags", entry.flags);
Byeongjo Park25c3a3d2020-06-12 17:24:21 +0900315 (*outBuffer)->meta()->setInt64("frameIndex", entry.ordinal.frameIndex.peekll());
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700316 ALOGV("[%s] popFromStashAndRegister: "
317 "out buffer index = %zu [%p] => %p + %zu (%lld)",
318 mName, *index, outBuffer->get(),
319 (*outBuffer)->data(), (*outBuffer)->size(),
320 (long long)entry.timestamp);
321
322 // The front entry of mPending will be removed now that the registration
323 // succeeded.
324 mPending.pop_front();
325 return NOTIFY_CLIENT;
326}
327
328bool OutputBuffers::popPending(StashEntry *entry) {
329 if (mPending.empty()) {
330 return false;
331 }
332 *entry = mPending.front();
333 mPending.pop_front();
334 return true;
335}
336
337void OutputBuffers::deferPending(const OutputBuffers::StashEntry &entry) {
338 mPending.push_front(entry);
339}
340
341bool OutputBuffers::hasPending() const {
342 return !mPending.empty();
343}
344
345bool OutputBuffers::less(
346 const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2) const {
347 switch (mKey) {
348 case C2Config::ORDINAL: return o1.frameIndex < o2.frameIndex;
349 case C2Config::TIMESTAMP: return o1.timestamp < o2.timestamp;
350 case C2Config::CUSTOM: return o1.customOrdinal < o2.customOrdinal;
351 default:
352 ALOGD("Unrecognized key; default to timestamp");
353 return o1.frameIndex < o2.frameIndex;
354 }
355}
356
Wonsik Kim469c8342019-04-11 16:46:09 -0700357// LocalBufferPool
358
Wonsik Kim41d83432020-04-27 16:40:49 -0700359constexpr size_t kInitialPoolCapacity = kMaxLinearBufferSize;
360constexpr size_t kMaxPoolCapacity = kMaxLinearBufferSize * 32;
361
362std::shared_ptr<LocalBufferPool> LocalBufferPool::Create() {
363 return std::shared_ptr<LocalBufferPool>(new LocalBufferPool(kInitialPoolCapacity));
Wonsik Kim469c8342019-04-11 16:46:09 -0700364}
365
366sp<ABuffer> LocalBufferPool::newBuffer(size_t capacity) {
367 Mutex::Autolock lock(mMutex);
368 auto it = std::find_if(
369 mPool.begin(), mPool.end(),
370 [capacity](const std::vector<uint8_t> &vec) {
371 return vec.capacity() >= capacity;
372 });
373 if (it != mPool.end()) {
374 sp<ABuffer> buffer = new VectorBuffer(std::move(*it), shared_from_this());
375 mPool.erase(it);
376 return buffer;
377 }
378 if (mUsedSize + capacity > mPoolCapacity) {
379 while (!mPool.empty()) {
380 mUsedSize -= mPool.back().capacity();
381 mPool.pop_back();
382 }
Wonsik Kim41d83432020-04-27 16:40:49 -0700383 while (mUsedSize + capacity > mPoolCapacity && mPoolCapacity * 2 <= kMaxPoolCapacity) {
384 ALOGD("Increasing local buffer pool capacity from %zu to %zu",
385 mPoolCapacity, mPoolCapacity * 2);
386 mPoolCapacity *= 2;
387 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700388 if (mUsedSize + capacity > mPoolCapacity) {
389 ALOGD("mUsedSize = %zu, capacity = %zu, mPoolCapacity = %zu",
390 mUsedSize, capacity, mPoolCapacity);
391 return nullptr;
392 }
393 }
394 std::vector<uint8_t> vec(capacity);
395 mUsedSize += vec.capacity();
396 return new VectorBuffer(std::move(vec), shared_from_this());
397}
398
399LocalBufferPool::VectorBuffer::VectorBuffer(
400 std::vector<uint8_t> &&vec, const std::shared_ptr<LocalBufferPool> &pool)
401 : ABuffer(vec.data(), vec.capacity()),
402 mVec(std::move(vec)),
403 mPool(pool) {
404}
405
406LocalBufferPool::VectorBuffer::~VectorBuffer() {
407 std::shared_ptr<LocalBufferPool> pool = mPool.lock();
408 if (pool) {
409 // If pool is alive, return the vector back to the pool so that
410 // it can be recycled.
411 pool->returnVector(std::move(mVec));
412 }
413}
414
415void LocalBufferPool::returnVector(std::vector<uint8_t> &&vec) {
416 Mutex::Autolock lock(mMutex);
417 mPool.push_front(std::move(vec));
418}
419
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700420// FlexBuffersImpl
421
Wonsik Kim469c8342019-04-11 16:46:09 -0700422size_t FlexBuffersImpl::assignSlot(const sp<Codec2Buffer> &buffer) {
423 for (size_t i = 0; i < mBuffers.size(); ++i) {
424 if (mBuffers[i].clientBuffer == nullptr
425 && mBuffers[i].compBuffer.expired()) {
426 mBuffers[i].clientBuffer = buffer;
427 return i;
428 }
429 }
430 mBuffers.push_back({ buffer, std::weak_ptr<C2Buffer>() });
431 return mBuffers.size() - 1;
432}
433
Wonsik Kim469c8342019-04-11 16:46:09 -0700434bool FlexBuffersImpl::releaseSlot(
435 const sp<MediaCodecBuffer> &buffer,
436 std::shared_ptr<C2Buffer> *c2buffer,
437 bool release) {
438 sp<Codec2Buffer> clientBuffer;
439 size_t index = mBuffers.size();
440 for (size_t i = 0; i < mBuffers.size(); ++i) {
441 if (mBuffers[i].clientBuffer == buffer) {
442 clientBuffer = mBuffers[i].clientBuffer;
443 if (release) {
444 mBuffers[i].clientBuffer.clear();
445 }
446 index = i;
447 break;
448 }
449 }
450 if (clientBuffer == nullptr) {
451 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
452 return false;
453 }
454 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
455 if (!result) {
456 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700457 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700458 mBuffers[index].compBuffer = result;
459 }
460 if (c2buffer) {
461 *c2buffer = result;
462 }
463 return true;
464}
465
466bool FlexBuffersImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
467 for (size_t i = 0; i < mBuffers.size(); ++i) {
468 std::shared_ptr<C2Buffer> compBuffer =
469 mBuffers[i].compBuffer.lock();
470 if (!compBuffer || compBuffer != c2buffer) {
471 continue;
472 }
473 mBuffers[i].compBuffer.reset();
474 ALOGV("[%s] codec released buffer #%zu", mName, i);
475 return true;
476 }
477 ALOGV("[%s] codec released an unknown buffer", mName);
478 return false;
479}
480
481void FlexBuffersImpl::flush() {
482 ALOGV("[%s] buffers are flushed %zu", mName, mBuffers.size());
483 mBuffers.clear();
484}
485
Wonsik Kim0487b782020-10-28 11:45:50 -0700486size_t FlexBuffersImpl::numActiveSlots() const {
Wonsik Kim469c8342019-04-11 16:46:09 -0700487 return std::count_if(
488 mBuffers.begin(), mBuffers.end(),
489 [](const Entry &entry) {
Wonsik Kim0487b782020-10-28 11:45:50 -0700490 return (entry.clientBuffer != nullptr
491 || !entry.compBuffer.expired());
Wonsik Kim469c8342019-04-11 16:46:09 -0700492 });
493}
494
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700495size_t FlexBuffersImpl::numComponentBuffers() const {
496 return std::count_if(
497 mBuffers.begin(), mBuffers.end(),
498 [](const Entry &entry) {
499 return !entry.compBuffer.expired();
500 });
501}
502
Wonsik Kim469c8342019-04-11 16:46:09 -0700503// BuffersArrayImpl
504
505void BuffersArrayImpl::initialize(
506 const FlexBuffersImpl &impl,
507 size_t minSize,
508 std::function<sp<Codec2Buffer>()> allocate) {
509 mImplName = impl.mImplName + "[N]";
510 mName = mImplName.c_str();
511 for (size_t i = 0; i < impl.mBuffers.size(); ++i) {
512 sp<Codec2Buffer> clientBuffer = impl.mBuffers[i].clientBuffer;
513 bool ownedByClient = (clientBuffer != nullptr);
514 if (!ownedByClient) {
515 clientBuffer = allocate();
516 }
517 mBuffers.push_back({ clientBuffer, impl.mBuffers[i].compBuffer, ownedByClient });
518 }
519 ALOGV("[%s] converted %zu buffers to array mode of %zu", mName, mBuffers.size(), minSize);
520 for (size_t i = impl.mBuffers.size(); i < minSize; ++i) {
521 mBuffers.push_back({ allocate(), std::weak_ptr<C2Buffer>(), false });
522 }
523}
524
525status_t BuffersArrayImpl::grabBuffer(
526 size_t *index,
527 sp<Codec2Buffer> *buffer,
528 std::function<bool(const sp<Codec2Buffer> &)> match) {
529 // allBuffersDontMatch remains true if all buffers are available but
530 // match() returns false for every buffer.
531 bool allBuffersDontMatch = true;
532 for (size_t i = 0; i < mBuffers.size(); ++i) {
533 if (!mBuffers[i].ownedByClient && mBuffers[i].compBuffer.expired()) {
534 if (match(mBuffers[i].clientBuffer)) {
535 mBuffers[i].ownedByClient = true;
536 *buffer = mBuffers[i].clientBuffer;
537 (*buffer)->meta()->clear();
538 (*buffer)->setRange(0, (*buffer)->capacity());
539 *index = i;
540 return OK;
541 }
542 } else {
543 allBuffersDontMatch = false;
544 }
545 }
546 return allBuffersDontMatch ? NO_MEMORY : WOULD_BLOCK;
547}
548
549bool BuffersArrayImpl::returnBuffer(
550 const sp<MediaCodecBuffer> &buffer,
551 std::shared_ptr<C2Buffer> *c2buffer,
552 bool release) {
553 sp<Codec2Buffer> clientBuffer;
554 size_t index = mBuffers.size();
555 for (size_t i = 0; i < mBuffers.size(); ++i) {
556 if (mBuffers[i].clientBuffer == buffer) {
557 if (!mBuffers[i].ownedByClient) {
558 ALOGD("[%s] Client returned a buffer it does not own according to our record: %zu",
559 mName, i);
560 }
561 clientBuffer = mBuffers[i].clientBuffer;
562 if (release) {
563 mBuffers[i].ownedByClient = false;
564 }
565 index = i;
566 break;
567 }
568 }
569 if (clientBuffer == nullptr) {
570 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
571 return false;
572 }
573 ALOGV("[%s] %s: matching buffer found (index=%zu)", mName, __func__, index);
574 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
575 if (!result) {
576 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700577 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700578 mBuffers[index].compBuffer = result;
579 }
580 if (c2buffer) {
581 *c2buffer = result;
582 }
583 return true;
584}
585
586bool BuffersArrayImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
587 for (size_t i = 0; i < mBuffers.size(); ++i) {
588 std::shared_ptr<C2Buffer> compBuffer =
589 mBuffers[i].compBuffer.lock();
590 if (!compBuffer) {
591 continue;
592 }
593 if (c2buffer == compBuffer) {
594 if (mBuffers[i].ownedByClient) {
595 // This should not happen.
596 ALOGD("[%s] codec released a buffer owned by client "
597 "(index %zu)", mName, i);
598 }
599 mBuffers[i].compBuffer.reset();
600 ALOGV("[%s] codec released buffer #%zu(array mode)", mName, i);
601 return true;
602 }
603 }
604 ALOGV("[%s] codec released an unknown buffer (array mode)", mName);
605 return false;
606}
607
608void BuffersArrayImpl::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
609 array->clear();
610 for (const Entry &entry : mBuffers) {
611 array->push(entry.clientBuffer);
612 }
613}
614
615void BuffersArrayImpl::flush() {
616 for (Entry &entry : mBuffers) {
617 entry.ownedByClient = false;
618 }
619}
620
621void BuffersArrayImpl::realloc(std::function<sp<Codec2Buffer>()> alloc) {
622 size_t size = mBuffers.size();
623 mBuffers.clear();
624 for (size_t i = 0; i < size; ++i) {
625 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
626 }
627}
628
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700629void BuffersArrayImpl::grow(
630 size_t newSize, std::function<sp<Codec2Buffer>()> alloc) {
631 CHECK_LT(mBuffers.size(), newSize);
632 while (mBuffers.size() < newSize) {
633 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
634 }
635}
636
Wonsik Kim0487b782020-10-28 11:45:50 -0700637size_t BuffersArrayImpl::numActiveSlots() const {
Wonsik Kim469c8342019-04-11 16:46:09 -0700638 return std::count_if(
639 mBuffers.begin(), mBuffers.end(),
640 [](const Entry &entry) {
Wonsik Kim0487b782020-10-28 11:45:50 -0700641 return entry.ownedByClient || !entry.compBuffer.expired();
Wonsik Kim469c8342019-04-11 16:46:09 -0700642 });
643}
644
Wonsik Kima39882b2019-06-20 16:13:56 -0700645size_t BuffersArrayImpl::arraySize() const {
646 return mBuffers.size();
647}
648
Wonsik Kim469c8342019-04-11 16:46:09 -0700649// InputBuffersArray
650
651void InputBuffersArray::initialize(
652 const FlexBuffersImpl &impl,
653 size_t minSize,
654 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700655 mAllocate = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -0700656 mImpl.initialize(impl, minSize, allocate);
657}
658
659void InputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
660 mImpl.getArray(array);
661}
662
663bool InputBuffersArray::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
664 sp<Codec2Buffer> c2Buffer;
665 status_t err = mImpl.grabBuffer(index, &c2Buffer);
666 if (err == OK) {
667 c2Buffer->setFormat(mFormat);
668 handleImageData(c2Buffer);
669 *buffer = c2Buffer;
670 return true;
671 }
672 return false;
673}
674
675bool InputBuffersArray::releaseBuffer(
676 const sp<MediaCodecBuffer> &buffer,
677 std::shared_ptr<C2Buffer> *c2buffer,
678 bool release) {
679 return mImpl.returnBuffer(buffer, c2buffer, release);
680}
681
682bool InputBuffersArray::expireComponentBuffer(
683 const std::shared_ptr<C2Buffer> &c2buffer) {
684 return mImpl.expireComponentBuffer(c2buffer);
685}
686
687void InputBuffersArray::flush() {
688 mImpl.flush();
689}
690
Wonsik Kim0487b782020-10-28 11:45:50 -0700691size_t InputBuffersArray::numActiveSlots() const {
692 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700693}
694
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700695sp<Codec2Buffer> InputBuffersArray::createNewBuffer() {
696 return mAllocate();
697}
698
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800699// SlotInputBuffers
700
701bool SlotInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
702 sp<Codec2Buffer> newBuffer = createNewBuffer();
703 *index = mImpl.assignSlot(newBuffer);
704 *buffer = newBuffer;
705 return true;
706}
707
708bool SlotInputBuffers::releaseBuffer(
709 const sp<MediaCodecBuffer> &buffer,
710 std::shared_ptr<C2Buffer> *c2buffer,
711 bool release) {
712 return mImpl.releaseSlot(buffer, c2buffer, release);
713}
714
715bool SlotInputBuffers::expireComponentBuffer(
716 const std::shared_ptr<C2Buffer> &c2buffer) {
717 return mImpl.expireComponentBuffer(c2buffer);
718}
719
720void SlotInputBuffers::flush() {
721 mImpl.flush();
722}
723
724std::unique_ptr<InputBuffers> SlotInputBuffers::toArrayMode(size_t) {
725 TRESPASS("Array mode should not be called at non-legacy mode");
726 return nullptr;
727}
728
Wonsik Kim0487b782020-10-28 11:45:50 -0700729size_t SlotInputBuffers::numActiveSlots() const {
730 return mImpl.numActiveSlots();
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800731}
732
733sp<Codec2Buffer> SlotInputBuffers::createNewBuffer() {
734 return new DummyContainerBuffer{mFormat, nullptr};
735}
736
Wonsik Kim469c8342019-04-11 16:46:09 -0700737// LinearInputBuffers
738
739bool LinearInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700740 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700741 if (newBuffer == nullptr) {
742 return false;
743 }
744 *index = mImpl.assignSlot(newBuffer);
745 *buffer = newBuffer;
746 return true;
747}
748
749bool LinearInputBuffers::releaseBuffer(
750 const sp<MediaCodecBuffer> &buffer,
751 std::shared_ptr<C2Buffer> *c2buffer,
752 bool release) {
753 return mImpl.releaseSlot(buffer, c2buffer, release);
754}
755
756bool LinearInputBuffers::expireComponentBuffer(
757 const std::shared_ptr<C2Buffer> &c2buffer) {
758 return mImpl.expireComponentBuffer(c2buffer);
759}
760
761void LinearInputBuffers::flush() {
762 // This is no-op by default unless we're in array mode where we need to keep
763 // track of the flushed work.
764 mImpl.flush();
765}
766
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700767std::unique_ptr<InputBuffers> LinearInputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700768 std::unique_ptr<InputBuffersArray> array(
769 new InputBuffersArray(mComponentName.c_str(), "1D-Input[N]"));
770 array->setPool(mPool);
771 array->setFormat(mFormat);
772 array->initialize(
773 mImpl,
774 size,
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700775 [pool = mPool, format = mFormat] () -> sp<Codec2Buffer> {
776 return Alloc(pool, format);
777 });
Wonsik Kim469c8342019-04-11 16:46:09 -0700778 return std::move(array);
779}
780
Wonsik Kim0487b782020-10-28 11:45:50 -0700781size_t LinearInputBuffers::numActiveSlots() const {
782 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700783}
784
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700785// static
786sp<Codec2Buffer> LinearInputBuffers::Alloc(
787 const std::shared_ptr<C2BlockPool> &pool, const sp<AMessage> &format) {
788 int32_t capacity = kLinearBufferSize;
789 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
790 if ((size_t)capacity > kMaxLinearBufferSize) {
791 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
792 capacity = kMaxLinearBufferSize;
793 }
794
795 // TODO: read usage from intf
Wonsik Kim469c8342019-04-11 16:46:09 -0700796 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
797 std::shared_ptr<C2LinearBlock> block;
798
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700799 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700800 if (err != C2_OK) {
801 return nullptr;
802 }
803
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700804 return LinearBlockBuffer::Allocate(format, block);
805}
806
807sp<Codec2Buffer> LinearInputBuffers::createNewBuffer() {
808 return Alloc(mPool, mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -0700809}
810
811// EncryptedLinearInputBuffers
812
813EncryptedLinearInputBuffers::EncryptedLinearInputBuffers(
814 bool secure,
815 const sp<MemoryDealer> &dealer,
816 const sp<ICrypto> &crypto,
817 int32_t heapSeqNum,
818 size_t capacity,
819 size_t numInputSlots,
820 const char *componentName, const char *name)
821 : LinearInputBuffers(componentName, name),
822 mUsage({0, 0}),
823 mDealer(dealer),
824 mCrypto(crypto),
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700825 mMemoryVector(new std::vector<Entry>){
Wonsik Kim469c8342019-04-11 16:46:09 -0700826 if (secure) {
827 mUsage = { C2MemoryUsage::READ_PROTECTED, 0 };
828 } else {
829 mUsage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
830 }
831 for (size_t i = 0; i < numInputSlots; ++i) {
832 sp<IMemory> memory = mDealer->allocate(capacity);
833 if (memory == nullptr) {
834 ALOGD("[%s] Failed to allocate memory from dealer: only %zu slots allocated",
835 mName, i);
836 break;
837 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700838 mMemoryVector->push_back({std::weak_ptr<C2LinearBlock>(), memory, heapSeqNum});
Wonsik Kim469c8342019-04-11 16:46:09 -0700839 }
840}
841
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700842std::unique_ptr<InputBuffers> EncryptedLinearInputBuffers::toArrayMode(size_t size) {
843 std::unique_ptr<InputBuffersArray> array(
844 new InputBuffersArray(mComponentName.c_str(), "1D-EncryptedInput[N]"));
845 array->setPool(mPool);
846 array->setFormat(mFormat);
847 array->initialize(
848 mImpl,
849 size,
850 [pool = mPool,
851 format = mFormat,
852 usage = mUsage,
853 memoryVector = mMemoryVector] () -> sp<Codec2Buffer> {
854 return Alloc(pool, format, usage, memoryVector);
855 });
856 return std::move(array);
857}
858
859
860// static
861sp<Codec2Buffer> EncryptedLinearInputBuffers::Alloc(
862 const std::shared_ptr<C2BlockPool> &pool,
863 const sp<AMessage> &format,
864 C2MemoryUsage usage,
865 const std::shared_ptr<std::vector<EncryptedLinearInputBuffers::Entry>> &memoryVector) {
866 int32_t capacity = kLinearBufferSize;
867 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
868 if ((size_t)capacity > kMaxLinearBufferSize) {
869 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
870 capacity = kMaxLinearBufferSize;
871 }
872
Wonsik Kim469c8342019-04-11 16:46:09 -0700873 sp<IMemory> memory;
874 size_t slot = 0;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700875 int32_t heapSeqNum = -1;
876 for (; slot < memoryVector->size(); ++slot) {
877 if (memoryVector->at(slot).block.expired()) {
878 memory = memoryVector->at(slot).memory;
879 heapSeqNum = memoryVector->at(slot).heapSeqNum;
Wonsik Kim469c8342019-04-11 16:46:09 -0700880 break;
881 }
882 }
883 if (memory == nullptr) {
884 return nullptr;
885 }
886
887 std::shared_ptr<C2LinearBlock> block;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700888 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700889 if (err != C2_OK || block == nullptr) {
890 return nullptr;
891 }
892
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700893 memoryVector->at(slot).block = block;
894 return new EncryptedLinearBlockBuffer(format, block, memory, heapSeqNum);
895}
896
897sp<Codec2Buffer> EncryptedLinearInputBuffers::createNewBuffer() {
898 // TODO: android_2020
899 return nullptr;
Wonsik Kim469c8342019-04-11 16:46:09 -0700900}
901
902// GraphicMetadataInputBuffers
903
904GraphicMetadataInputBuffers::GraphicMetadataInputBuffers(
905 const char *componentName, const char *name)
906 : InputBuffers(componentName, name),
907 mImpl(mName),
908 mStore(GetCodec2PlatformAllocatorStore()) { }
909
910bool GraphicMetadataInputBuffers::requestNewBuffer(
911 size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700912 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700913 if (newBuffer == nullptr) {
914 return false;
915 }
916 *index = mImpl.assignSlot(newBuffer);
917 *buffer = newBuffer;
918 return true;
919}
920
921bool GraphicMetadataInputBuffers::releaseBuffer(
922 const sp<MediaCodecBuffer> &buffer,
923 std::shared_ptr<C2Buffer> *c2buffer,
924 bool release) {
925 return mImpl.releaseSlot(buffer, c2buffer, release);
926}
927
928bool GraphicMetadataInputBuffers::expireComponentBuffer(
929 const std::shared_ptr<C2Buffer> &c2buffer) {
930 return mImpl.expireComponentBuffer(c2buffer);
931}
932
933void GraphicMetadataInputBuffers::flush() {
934 // This is no-op by default unless we're in array mode where we need to keep
935 // track of the flushed work.
936}
937
938std::unique_ptr<InputBuffers> GraphicMetadataInputBuffers::toArrayMode(
939 size_t size) {
940 std::shared_ptr<C2Allocator> alloc;
941 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
942 if (err != C2_OK) {
943 return nullptr;
944 }
945 std::unique_ptr<InputBuffersArray> array(
946 new InputBuffersArray(mComponentName.c_str(), "2D-MetaInput[N]"));
947 array->setPool(mPool);
948 array->setFormat(mFormat);
949 array->initialize(
950 mImpl,
951 size,
952 [format = mFormat, alloc]() -> sp<Codec2Buffer> {
953 return new GraphicMetadataBuffer(format, alloc);
954 });
955 return std::move(array);
956}
957
Wonsik Kim0487b782020-10-28 11:45:50 -0700958size_t GraphicMetadataInputBuffers::numActiveSlots() const {
959 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700960}
961
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700962sp<Codec2Buffer> GraphicMetadataInputBuffers::createNewBuffer() {
963 std::shared_ptr<C2Allocator> alloc;
964 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
965 if (err != C2_OK) {
966 return nullptr;
967 }
968 return new GraphicMetadataBuffer(mFormat, alloc);
969}
970
Wonsik Kim469c8342019-04-11 16:46:09 -0700971// GraphicInputBuffers
972
973GraphicInputBuffers::GraphicInputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -0700974 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -0700975 : InputBuffers(componentName, name),
976 mImpl(mName),
Wonsik Kim41d83432020-04-27 16:40:49 -0700977 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -0700978
979bool GraphicInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700980 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700981 if (newBuffer == nullptr) {
982 return false;
983 }
984 *index = mImpl.assignSlot(newBuffer);
985 handleImageData(newBuffer);
986 *buffer = newBuffer;
987 return true;
988}
989
990bool GraphicInputBuffers::releaseBuffer(
991 const sp<MediaCodecBuffer> &buffer,
992 std::shared_ptr<C2Buffer> *c2buffer,
993 bool release) {
994 return mImpl.releaseSlot(buffer, c2buffer, release);
995}
996
997bool GraphicInputBuffers::expireComponentBuffer(
998 const std::shared_ptr<C2Buffer> &c2buffer) {
999 return mImpl.expireComponentBuffer(c2buffer);
1000}
1001
1002void GraphicInputBuffers::flush() {
1003 // This is no-op by default unless we're in array mode where we need to keep
1004 // track of the flushed work.
1005}
1006
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001007static uint32_t extractPixelFormat(const sp<AMessage> &format) {
1008 int32_t frameworkColorFormat = 0;
1009 if (!format->findInt32("android._color-format", &frameworkColorFormat)) {
1010 return PIXEL_FORMAT_UNKNOWN;
1011 }
1012 uint32_t pixelFormat = PIXEL_FORMAT_UNKNOWN;
1013 if (C2Mapper::mapPixelFormatFrameworkToCodec(frameworkColorFormat, &pixelFormat)) {
1014 return pixelFormat;
1015 }
1016 return PIXEL_FORMAT_UNKNOWN;
1017}
1018
Wonsik Kim469c8342019-04-11 16:46:09 -07001019std::unique_ptr<InputBuffers> GraphicInputBuffers::toArrayMode(size_t size) {
1020 std::unique_ptr<InputBuffersArray> array(
1021 new InputBuffersArray(mComponentName.c_str(), "2D-BB-Input[N]"));
1022 array->setPool(mPool);
1023 array->setFormat(mFormat);
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001024 uint32_t pixelFormat = extractPixelFormat(mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -07001025 array->initialize(
1026 mImpl,
1027 size,
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001028 [pool = mPool, format = mFormat, lbp = mLocalBufferPool, pixelFormat]()
1029 -> sp<Codec2Buffer> {
Wonsik Kim469c8342019-04-11 16:46:09 -07001030 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
1031 return AllocateGraphicBuffer(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001032 pool, format, pixelFormat, usage, lbp);
Wonsik Kim469c8342019-04-11 16:46:09 -07001033 });
1034 return std::move(array);
1035}
1036
Wonsik Kim0487b782020-10-28 11:45:50 -07001037size_t GraphicInputBuffers::numActiveSlots() const {
1038 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001039}
1040
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001041sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
1042 // TODO: read usage from intf
1043 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
1044 return AllocateGraphicBuffer(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001045 mPool, mFormat, extractPixelFormat(mFormat), usage, mLocalBufferPool);
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001046}
1047
Wonsik Kim469c8342019-04-11 16:46:09 -07001048// OutputBuffersArray
1049
1050void OutputBuffersArray::initialize(
1051 const FlexBuffersImpl &impl,
1052 size_t minSize,
1053 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001054 mAlloc = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -07001055 mImpl.initialize(impl, minSize, allocate);
1056}
1057
1058status_t OutputBuffersArray::registerBuffer(
1059 const std::shared_ptr<C2Buffer> &buffer,
1060 size_t *index,
1061 sp<MediaCodecBuffer> *clientBuffer) {
1062 sp<Codec2Buffer> c2Buffer;
1063 status_t err = mImpl.grabBuffer(
1064 index,
1065 &c2Buffer,
1066 [buffer](const sp<Codec2Buffer> &clientBuffer) {
1067 return clientBuffer->canCopy(buffer);
1068 });
1069 if (err == WOULD_BLOCK) {
1070 ALOGV("[%s] buffers temporarily not available", mName);
1071 return err;
1072 } else if (err != OK) {
1073 ALOGD("[%s] grabBuffer failed: %d", mName, err);
1074 return err;
1075 }
1076 c2Buffer->setFormat(mFormat);
1077 if (!c2Buffer->copy(buffer)) {
1078 ALOGD("[%s] copy buffer failed", mName);
1079 return WOULD_BLOCK;
1080 }
1081 submit(c2Buffer);
1082 handleImageData(c2Buffer);
1083 *clientBuffer = c2Buffer;
1084 ALOGV("[%s] grabbed buffer %zu", mName, *index);
1085 return OK;
1086}
1087
1088status_t OutputBuffersArray::registerCsd(
1089 const C2StreamInitDataInfo::output *csd,
1090 size_t *index,
1091 sp<MediaCodecBuffer> *clientBuffer) {
1092 sp<Codec2Buffer> c2Buffer;
1093 status_t err = mImpl.grabBuffer(
1094 index,
1095 &c2Buffer,
1096 [csd](const sp<Codec2Buffer> &clientBuffer) {
1097 return clientBuffer->base() != nullptr
1098 && clientBuffer->capacity() >= csd->flexCount();
1099 });
1100 if (err != OK) {
1101 return err;
1102 }
1103 memcpy(c2Buffer->base(), csd->m.value, csd->flexCount());
1104 c2Buffer->setRange(0, csd->flexCount());
1105 c2Buffer->setFormat(mFormat);
1106 *clientBuffer = c2Buffer;
1107 return OK;
1108}
1109
1110bool OutputBuffersArray::releaseBuffer(
1111 const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) {
1112 return mImpl.returnBuffer(buffer, c2buffer, true);
1113}
1114
1115void OutputBuffersArray::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1116 (void)flushedWork;
1117 mImpl.flush();
1118 if (mSkipCutBuffer != nullptr) {
1119 mSkipCutBuffer->clear();
1120 }
1121}
1122
1123void OutputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
1124 mImpl.getArray(array);
1125}
1126
Wonsik Kim0487b782020-10-28 11:45:50 -07001127size_t OutputBuffersArray::numActiveSlots() const {
1128 return mImpl.numActiveSlots();
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001129}
1130
Wonsik Kim469c8342019-04-11 16:46:09 -07001131void OutputBuffersArray::realloc(const std::shared_ptr<C2Buffer> &c2buffer) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001132 switch (c2buffer->data().type()) {
1133 case C2BufferData::LINEAR: {
1134 uint32_t size = kLinearBufferSize;
Nick Desaulniersd09eaea2019-10-07 20:19:39 -07001135 const std::vector<C2ConstLinearBlock> &linear_blocks = c2buffer->data().linearBlocks();
1136 const uint32_t block_size = linear_blocks.front().size();
1137 if (block_size < kMaxLinearBufferSize / 2) {
1138 size = block_size * 2;
Wonsik Kim469c8342019-04-11 16:46:09 -07001139 } else {
1140 size = kMaxLinearBufferSize;
1141 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001142 mAlloc = [format = mFormat, size] {
Wonsik Kim469c8342019-04-11 16:46:09 -07001143 return new LocalLinearBuffer(format, new ABuffer(size));
1144 };
Wonsik Kima39882b2019-06-20 16:13:56 -07001145 ALOGD("[%s] reallocating with linear buffer of size %u", mName, size);
Wonsik Kim469c8342019-04-11 16:46:09 -07001146 break;
1147 }
1148
Wonsik Kima39882b2019-06-20 16:13:56 -07001149 case C2BufferData::GRAPHIC: {
1150 // This is only called for RawGraphicOutputBuffers.
1151 mAlloc = [format = mFormat,
Wonsik Kim41d83432020-04-27 16:40:49 -07001152 lbp = LocalBufferPool::Create()] {
Wonsik Kima39882b2019-06-20 16:13:56 -07001153 return ConstGraphicBlockBuffer::AllocateEmpty(
1154 format,
1155 [lbp](size_t capacity) {
1156 return lbp->newBuffer(capacity);
1157 });
1158 };
1159 ALOGD("[%s] reallocating with graphic buffer: format = %s",
1160 mName, mFormat->debugString().c_str());
1161 break;
1162 }
Wonsik Kim469c8342019-04-11 16:46:09 -07001163
1164 case C2BufferData::INVALID: [[fallthrough]];
1165 case C2BufferData::LINEAR_CHUNKS: [[fallthrough]];
1166 case C2BufferData::GRAPHIC_CHUNKS: [[fallthrough]];
1167 default:
1168 ALOGD("Unsupported type: %d", (int)c2buffer->data().type());
1169 return;
1170 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001171 mImpl.realloc(mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -07001172}
1173
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001174void OutputBuffersArray::grow(size_t newSize) {
1175 mImpl.grow(newSize, mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -07001176}
1177
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001178void OutputBuffersArray::transferFrom(OutputBuffers* source) {
1179 mFormat = source->mFormat;
1180 mSkipCutBuffer = source->mSkipCutBuffer;
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001181 mPending = std::move(source->mPending);
1182 mReorderStash = std::move(source->mReorderStash);
1183 mDepth = source->mDepth;
1184 mKey = source->mKey;
1185}
1186
Wonsik Kim469c8342019-04-11 16:46:09 -07001187// FlexOutputBuffers
1188
1189status_t FlexOutputBuffers::registerBuffer(
1190 const std::shared_ptr<C2Buffer> &buffer,
1191 size_t *index,
1192 sp<MediaCodecBuffer> *clientBuffer) {
1193 sp<Codec2Buffer> newBuffer = wrap(buffer);
1194 if (newBuffer == nullptr) {
1195 return NO_MEMORY;
1196 }
1197 newBuffer->setFormat(mFormat);
1198 *index = mImpl.assignSlot(newBuffer);
1199 handleImageData(newBuffer);
1200 *clientBuffer = newBuffer;
1201 ALOGV("[%s] registered buffer %zu", mName, *index);
1202 return OK;
1203}
1204
1205status_t FlexOutputBuffers::registerCsd(
1206 const C2StreamInitDataInfo::output *csd,
1207 size_t *index,
1208 sp<MediaCodecBuffer> *clientBuffer) {
1209 sp<Codec2Buffer> newBuffer = new LocalLinearBuffer(
1210 mFormat, ABuffer::CreateAsCopy(csd->m.value, csd->flexCount()));
1211 *index = mImpl.assignSlot(newBuffer);
1212 *clientBuffer = newBuffer;
1213 return OK;
1214}
1215
1216bool FlexOutputBuffers::releaseBuffer(
1217 const sp<MediaCodecBuffer> &buffer,
1218 std::shared_ptr<C2Buffer> *c2buffer) {
1219 return mImpl.releaseSlot(buffer, c2buffer, true);
1220}
1221
1222void FlexOutputBuffers::flush(
1223 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1224 (void) flushedWork;
1225 // This is no-op by default unless we're in array mode where we need to keep
1226 // track of the flushed work.
1227}
1228
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001229std::unique_ptr<OutputBuffersArray> FlexOutputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001230 std::unique_ptr<OutputBuffersArray> array(new OutputBuffersArray(mComponentName.c_str()));
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001231 array->transferFrom(this);
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001232 std::function<sp<Codec2Buffer>()> alloc = getAlloc();
1233 array->initialize(mImpl, size, alloc);
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001234 return array;
Wonsik Kim469c8342019-04-11 16:46:09 -07001235}
1236
Wonsik Kim0487b782020-10-28 11:45:50 -07001237size_t FlexOutputBuffers::numActiveSlots() const {
1238 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001239}
1240
1241// LinearOutputBuffers
1242
1243void LinearOutputBuffers::flush(
1244 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1245 if (mSkipCutBuffer != nullptr) {
1246 mSkipCutBuffer->clear();
1247 }
1248 FlexOutputBuffers::flush(flushedWork);
1249}
1250
1251sp<Codec2Buffer> LinearOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1252 if (buffer == nullptr) {
1253 ALOGV("[%s] using a dummy buffer", mName);
1254 return new LocalLinearBuffer(mFormat, new ABuffer(0));
1255 }
1256 if (buffer->data().type() != C2BufferData::LINEAR) {
1257 ALOGV("[%s] non-linear buffer %d", mName, buffer->data().type());
1258 // We expect linear output buffers from the component.
1259 return nullptr;
1260 }
1261 if (buffer->data().linearBlocks().size() != 1u) {
1262 ALOGV("[%s] no linear buffers", mName);
1263 // We expect one and only one linear block from the component.
1264 return nullptr;
1265 }
1266 sp<Codec2Buffer> clientBuffer = ConstLinearBlockBuffer::Allocate(mFormat, buffer);
1267 if (clientBuffer == nullptr) {
1268 ALOGD("[%s] ConstLinearBlockBuffer::Allocate failed", mName);
1269 return nullptr;
1270 }
1271 submit(clientBuffer);
1272 return clientBuffer;
1273}
1274
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001275std::function<sp<Codec2Buffer>()> LinearOutputBuffers::getAlloc() {
1276 return [format = mFormat]{
1277 // TODO: proper max output size
1278 return new LocalLinearBuffer(format, new ABuffer(kLinearBufferSize));
1279 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001280}
1281
1282// GraphicOutputBuffers
1283
1284sp<Codec2Buffer> GraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1285 return new DummyContainerBuffer(mFormat, buffer);
1286}
1287
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001288std::function<sp<Codec2Buffer>()> GraphicOutputBuffers::getAlloc() {
1289 return [format = mFormat]{
1290 return new DummyContainerBuffer(format);
1291 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001292}
1293
1294// RawGraphicOutputBuffers
1295
1296RawGraphicOutputBuffers::RawGraphicOutputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -07001297 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -07001298 : FlexOutputBuffers(componentName, name),
Wonsik Kim41d83432020-04-27 16:40:49 -07001299 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -07001300
1301sp<Codec2Buffer> RawGraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1302 if (buffer == nullptr) {
1303 sp<Codec2Buffer> c2buffer = ConstGraphicBlockBuffer::AllocateEmpty(
1304 mFormat,
1305 [lbp = mLocalBufferPool](size_t capacity) {
1306 return lbp->newBuffer(capacity);
1307 });
1308 if (c2buffer == nullptr) {
1309 ALOGD("[%s] ConstGraphicBlockBuffer::AllocateEmpty failed", mName);
1310 return nullptr;
1311 }
1312 c2buffer->setRange(0, 0);
1313 return c2buffer;
1314 } else {
1315 return ConstGraphicBlockBuffer::Allocate(
1316 mFormat,
1317 buffer,
1318 [lbp = mLocalBufferPool](size_t capacity) {
1319 return lbp->newBuffer(capacity);
1320 });
1321 }
1322}
1323
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001324std::function<sp<Codec2Buffer>()> RawGraphicOutputBuffers::getAlloc() {
1325 return [format = mFormat, lbp = mLocalBufferPool]{
1326 return ConstGraphicBlockBuffer::AllocateEmpty(
1327 format,
1328 [lbp](size_t capacity) {
1329 return lbp->newBuffer(capacity);
1330 });
1331 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001332}
1333
1334} // namespace android