blob: 74f13196b87bcb0222f394d4476fa69358058819 [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"
30
31namespace android {
32
33namespace {
34
35sp<GraphicBlockBuffer> AllocateGraphicBuffer(
36 const std::shared_ptr<C2BlockPool> &pool,
37 const sp<AMessage> &format,
38 uint32_t pixelFormat,
39 const C2MemoryUsage &usage,
40 const std::shared_ptr<LocalBufferPool> &localBufferPool) {
41 int32_t width, height;
42 if (!format->findInt32("width", &width) || !format->findInt32("height", &height)) {
43 ALOGD("format lacks width or height");
44 return nullptr;
45 }
46
47 std::shared_ptr<C2GraphicBlock> block;
48 c2_status_t err = pool->fetchGraphicBlock(
49 width, height, pixelFormat, usage, &block);
50 if (err != C2_OK) {
51 ALOGD("fetch graphic block failed: %d", err);
52 return nullptr;
53 }
54
55 return GraphicBlockBuffer::Allocate(
56 format,
57 block,
58 [localBufferPool](size_t capacity) {
59 return localBufferPool->newBuffer(capacity);
60 });
61}
62
63} // namespace
64
65// CCodecBuffers
66
67void CCodecBuffers::setFormat(const sp<AMessage> &format) {
68 CHECK(format != nullptr);
69 mFormat = format;
70}
71
72sp<AMessage> CCodecBuffers::dupFormat() {
73 return mFormat != nullptr ? mFormat->dup() : nullptr;
74}
75
76void CCodecBuffers::handleImageData(const sp<Codec2Buffer> &buffer) {
77 sp<ABuffer> imageDataCandidate = buffer->getImageData();
78 if (imageDataCandidate == nullptr) {
79 return;
80 }
81 sp<ABuffer> imageData;
82 if (!mFormat->findBuffer("image-data", &imageData)
83 || imageDataCandidate->size() != imageData->size()
84 || memcmp(imageDataCandidate->data(), imageData->data(), imageData->size()) != 0) {
85 ALOGD("[%s] updating image-data", mName);
86 sp<AMessage> newFormat = dupFormat();
87 newFormat->setBuffer("image-data", imageDataCandidate);
88 MediaImage2 *img = (MediaImage2*)imageDataCandidate->data();
89 if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
90 int32_t stride = img->mPlane[0].mRowInc;
91 newFormat->setInt32(KEY_STRIDE, stride);
92 ALOGD("[%s] updating stride = %d", mName, stride);
93 if (img->mNumPlanes > 1 && stride > 0) {
Taehwan Kimfd9b8092020-09-17 12:26:40 +090094 int64_t offsetDelta =
95 (int64_t)img->mPlane[1].mOffset - (int64_t)img->mPlane[0].mOffset;
96 int32_t vstride = int32_t(offsetDelta / stride);
Wonsik Kim469c8342019-04-11 16:46:09 -070097 newFormat->setInt32(KEY_SLICE_HEIGHT, vstride);
98 ALOGD("[%s] updating vstride = %d", mName, vstride);
99 }
100 }
101 setFormat(newFormat);
102 buffer->setFormat(newFormat);
103 }
104}
105
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700106// InputBuffers
107
108sp<Codec2Buffer> InputBuffers::cloneAndReleaseBuffer(const sp<MediaCodecBuffer> &buffer) {
109 sp<Codec2Buffer> copy = createNewBuffer();
110 if (copy == nullptr) {
111 return nullptr;
112 }
113 std::shared_ptr<C2Buffer> c2buffer;
114 if (!releaseBuffer(buffer, &c2buffer, true)) {
115 return nullptr;
116 }
117 if (!copy->canCopy(c2buffer)) {
118 return nullptr;
119 }
120 if (!copy->copy(c2buffer)) {
121 return nullptr;
122 }
123 return copy;
124}
125
Wonsik Kim469c8342019-04-11 16:46:09 -0700126// OutputBuffers
127
Wonsik Kim41d83432020-04-27 16:40:49 -0700128OutputBuffers::OutputBuffers(const char *componentName, const char *name)
129 : CCodecBuffers(componentName, name) { }
130
131OutputBuffers::~OutputBuffers() = default;
132
Wonsik Kim469c8342019-04-11 16:46:09 -0700133void OutputBuffers::initSkipCutBuffer(
134 int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount) {
135 CHECK(mSkipCutBuffer == nullptr);
136 mDelay = delay;
137 mPadding = padding;
138 mSampleRate = sampleRate;
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700139 mChannelCount = channelCount;
140 setSkipCutBuffer(delay, padding);
Wonsik Kim469c8342019-04-11 16:46:09 -0700141}
142
143void OutputBuffers::updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount) {
144 if (mSkipCutBuffer == nullptr) {
145 return;
146 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700147 if (mSampleRate == sampleRate && mChannelCount == channelCount) {
148 return;
149 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700150 int32_t delay = mDelay;
151 int32_t padding = mPadding;
152 if (sampleRate != mSampleRate) {
153 delay = ((int64_t)delay * sampleRate) / mSampleRate;
154 padding = ((int64_t)padding * sampleRate) / mSampleRate;
155 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700156 mSampleRate = sampleRate;
157 mChannelCount = channelCount;
158 setSkipCutBuffer(delay, padding);
Wonsik Kim469c8342019-04-11 16:46:09 -0700159}
160
Wonsik Kima08cd2b2020-11-10 11:54:15 -0800161void OutputBuffers::updateSkipCutBuffer(const sp<AMessage> &format) {
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700162 AString mediaType;
163 if (format->findString(KEY_MIME, &mediaType)
164 && mediaType == MIMETYPE_AUDIO_RAW) {
165 int32_t channelCount;
166 int32_t sampleRate;
167 if (format->findInt32(KEY_CHANNEL_COUNT, &channelCount)
168 && format->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
169 updateSkipCutBuffer(sampleRate, channelCount);
170 }
171 }
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700172}
173
Wonsik Kim469c8342019-04-11 16:46:09 -0700174void OutputBuffers::submit(const sp<MediaCodecBuffer> &buffer) {
175 if (mSkipCutBuffer != nullptr) {
176 mSkipCutBuffer->submit(buffer);
177 }
178}
179
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700180void OutputBuffers::setSkipCutBuffer(int32_t skip, int32_t cut) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700181 if (mSkipCutBuffer != nullptr) {
182 size_t prevSize = mSkipCutBuffer->size();
183 if (prevSize != 0u) {
184 ALOGD("[%s] Replacing SkipCutBuffer holding %zu bytes", mName, prevSize);
185 }
186 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700187 mSkipCutBuffer = new SkipCutBuffer(skip, cut, mChannelCount);
Wonsik Kim469c8342019-04-11 16:46:09 -0700188}
189
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700190void OutputBuffers::clearStash() {
191 mPending.clear();
192 mReorderStash.clear();
193 mDepth = 0;
194 mKey = C2Config::ORDINAL;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700195}
196
197void OutputBuffers::flushStash() {
198 for (StashEntry& e : mPending) {
199 e.notify = false;
200 }
201 for (StashEntry& e : mReorderStash) {
202 e.notify = false;
203 }
204}
205
206uint32_t OutputBuffers::getReorderDepth() const {
207 return mDepth;
208}
209
210void OutputBuffers::setReorderDepth(uint32_t depth) {
211 mPending.splice(mPending.end(), mReorderStash);
212 mDepth = depth;
213}
214
215void OutputBuffers::setReorderKey(C2Config::ordinal_key_t key) {
216 mPending.splice(mPending.end(), mReorderStash);
217 mKey = key;
218}
219
220void OutputBuffers::pushToStash(
221 const std::shared_ptr<C2Buffer>& buffer,
222 bool notify,
223 int64_t timestamp,
224 int32_t flags,
225 const sp<AMessage>& format,
226 const C2WorkOrdinalStruct& ordinal) {
227 bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;
228 if (!buffer && eos) {
229 // TRICKY: we may be violating ordering of the stash here. Because we
230 // don't expect any more emplace() calls after this, the ordering should
231 // not matter.
232 mReorderStash.emplace_back(
233 buffer, notify, timestamp, flags, format, ordinal);
234 } else {
235 flags = flags & ~MediaCodec::BUFFER_FLAG_EOS;
236 auto it = mReorderStash.begin();
237 for (; it != mReorderStash.end(); ++it) {
238 if (less(ordinal, it->ordinal)) {
239 break;
240 }
241 }
242 mReorderStash.emplace(it,
243 buffer, notify, timestamp, flags, format, ordinal);
244 if (eos) {
245 mReorderStash.back().flags =
246 mReorderStash.back().flags | MediaCodec::BUFFER_FLAG_EOS;
247 }
248 }
249 while (!mReorderStash.empty() && mReorderStash.size() > mDepth) {
250 mPending.push_back(mReorderStash.front());
251 mReorderStash.pop_front();
252 }
253 ALOGV("[%s] %s: pushToStash -- pending size = %zu", mName, __func__, mPending.size());
254}
255
256OutputBuffers::BufferAction OutputBuffers::popFromStashAndRegister(
257 std::shared_ptr<C2Buffer>* c2Buffer,
258 size_t* index,
259 sp<MediaCodecBuffer>* outBuffer) {
260 if (mPending.empty()) {
261 return SKIP;
262 }
263
264 // Retrieve the first entry.
265 StashEntry &entry = mPending.front();
266
267 *c2Buffer = entry.buffer;
268 sp<AMessage> outputFormat = entry.format;
269
Wonsik Kima08cd2b2020-11-10 11:54:15 -0800270 if (entry.notify && mFormat != outputFormat) {
271 updateSkipCutBuffer(outputFormat);
272 sp<ABuffer> imageData;
273 if (mFormat->findBuffer("image-data", &imageData)) {
274 outputFormat->setBuffer("image-data", imageData);
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700275 }
Wonsik Kima08cd2b2020-11-10 11:54:15 -0800276 int32_t stride;
277 if (mFormat->findInt32(KEY_STRIDE, &stride)) {
278 outputFormat->setInt32(KEY_STRIDE, stride);
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700279 }
Wonsik Kima08cd2b2020-11-10 11:54:15 -0800280 int32_t sliceHeight;
281 if (mFormat->findInt32(KEY_SLICE_HEIGHT, &sliceHeight)) {
282 outputFormat->setInt32(KEY_SLICE_HEIGHT, sliceHeight);
283 }
284 ALOGV("[%s] popFromStashAndRegister: output format reference changed: %p -> %p",
285 mName, mFormat.get(), outputFormat.get());
286 ALOGD("[%s] popFromStashAndRegister: output format changed to %s",
287 mName, outputFormat->debugString().c_str());
288 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);
315 ALOGV("[%s] popFromStashAndRegister: "
316 "out buffer index = %zu [%p] => %p + %zu (%lld)",
317 mName, *index, outBuffer->get(),
318 (*outBuffer)->data(), (*outBuffer)->size(),
319 (long long)entry.timestamp);
320
321 // The front entry of mPending will be removed now that the registration
322 // succeeded.
323 mPending.pop_front();
324 return NOTIFY_CLIENT;
325}
326
327bool OutputBuffers::popPending(StashEntry *entry) {
328 if (mPending.empty()) {
329 return false;
330 }
331 *entry = mPending.front();
332 mPending.pop_front();
333 return true;
334}
335
336void OutputBuffers::deferPending(const OutputBuffers::StashEntry &entry) {
337 mPending.push_front(entry);
338}
339
340bool OutputBuffers::hasPending() const {
341 return !mPending.empty();
342}
343
344bool OutputBuffers::less(
345 const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2) const {
346 switch (mKey) {
347 case C2Config::ORDINAL: return o1.frameIndex < o2.frameIndex;
348 case C2Config::TIMESTAMP: return o1.timestamp < o2.timestamp;
349 case C2Config::CUSTOM: return o1.customOrdinal < o2.customOrdinal;
350 default:
351 ALOGD("Unrecognized key; default to timestamp");
352 return o1.frameIndex < o2.frameIndex;
353 }
354}
355
Wonsik Kim469c8342019-04-11 16:46:09 -0700356// LocalBufferPool
357
Wonsik Kim41d83432020-04-27 16:40:49 -0700358constexpr size_t kInitialPoolCapacity = kMaxLinearBufferSize;
359constexpr size_t kMaxPoolCapacity = kMaxLinearBufferSize * 32;
360
361std::shared_ptr<LocalBufferPool> LocalBufferPool::Create() {
362 return std::shared_ptr<LocalBufferPool>(new LocalBufferPool(kInitialPoolCapacity));
Wonsik Kim469c8342019-04-11 16:46:09 -0700363}
364
365sp<ABuffer> LocalBufferPool::newBuffer(size_t capacity) {
366 Mutex::Autolock lock(mMutex);
367 auto it = std::find_if(
368 mPool.begin(), mPool.end(),
369 [capacity](const std::vector<uint8_t> &vec) {
370 return vec.capacity() >= capacity;
371 });
372 if (it != mPool.end()) {
373 sp<ABuffer> buffer = new VectorBuffer(std::move(*it), shared_from_this());
374 mPool.erase(it);
375 return buffer;
376 }
377 if (mUsedSize + capacity > mPoolCapacity) {
378 while (!mPool.empty()) {
379 mUsedSize -= mPool.back().capacity();
380 mPool.pop_back();
381 }
Wonsik Kim41d83432020-04-27 16:40:49 -0700382 while (mUsedSize + capacity > mPoolCapacity && mPoolCapacity * 2 <= kMaxPoolCapacity) {
383 ALOGD("Increasing local buffer pool capacity from %zu to %zu",
384 mPoolCapacity, mPoolCapacity * 2);
385 mPoolCapacity *= 2;
386 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700387 if (mUsedSize + capacity > mPoolCapacity) {
388 ALOGD("mUsedSize = %zu, capacity = %zu, mPoolCapacity = %zu",
389 mUsedSize, capacity, mPoolCapacity);
390 return nullptr;
391 }
392 }
393 std::vector<uint8_t> vec(capacity);
394 mUsedSize += vec.capacity();
395 return new VectorBuffer(std::move(vec), shared_from_this());
396}
397
398LocalBufferPool::VectorBuffer::VectorBuffer(
399 std::vector<uint8_t> &&vec, const std::shared_ptr<LocalBufferPool> &pool)
400 : ABuffer(vec.data(), vec.capacity()),
401 mVec(std::move(vec)),
402 mPool(pool) {
403}
404
405LocalBufferPool::VectorBuffer::~VectorBuffer() {
406 std::shared_ptr<LocalBufferPool> pool = mPool.lock();
407 if (pool) {
408 // If pool is alive, return the vector back to the pool so that
409 // it can be recycled.
410 pool->returnVector(std::move(mVec));
411 }
412}
413
414void LocalBufferPool::returnVector(std::vector<uint8_t> &&vec) {
415 Mutex::Autolock lock(mMutex);
416 mPool.push_front(std::move(vec));
417}
418
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700419// FlexBuffersImpl
420
Wonsik Kim469c8342019-04-11 16:46:09 -0700421size_t FlexBuffersImpl::assignSlot(const sp<Codec2Buffer> &buffer) {
422 for (size_t i = 0; i < mBuffers.size(); ++i) {
423 if (mBuffers[i].clientBuffer == nullptr
424 && mBuffers[i].compBuffer.expired()) {
425 mBuffers[i].clientBuffer = buffer;
426 return i;
427 }
428 }
429 mBuffers.push_back({ buffer, std::weak_ptr<C2Buffer>() });
430 return mBuffers.size() - 1;
431}
432
Wonsik Kim469c8342019-04-11 16:46:09 -0700433bool FlexBuffersImpl::releaseSlot(
434 const sp<MediaCodecBuffer> &buffer,
435 std::shared_ptr<C2Buffer> *c2buffer,
436 bool release) {
437 sp<Codec2Buffer> clientBuffer;
438 size_t index = mBuffers.size();
439 for (size_t i = 0; i < mBuffers.size(); ++i) {
440 if (mBuffers[i].clientBuffer == buffer) {
441 clientBuffer = mBuffers[i].clientBuffer;
442 if (release) {
443 mBuffers[i].clientBuffer.clear();
444 }
445 index = i;
446 break;
447 }
448 }
449 if (clientBuffer == nullptr) {
450 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
451 return false;
452 }
453 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
454 if (!result) {
455 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700456 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700457 mBuffers[index].compBuffer = result;
458 }
459 if (c2buffer) {
460 *c2buffer = result;
461 }
462 return true;
463}
464
465bool FlexBuffersImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
466 for (size_t i = 0; i < mBuffers.size(); ++i) {
467 std::shared_ptr<C2Buffer> compBuffer =
468 mBuffers[i].compBuffer.lock();
469 if (!compBuffer || compBuffer != c2buffer) {
470 continue;
471 }
472 mBuffers[i].compBuffer.reset();
473 ALOGV("[%s] codec released buffer #%zu", mName, i);
474 return true;
475 }
476 ALOGV("[%s] codec released an unknown buffer", mName);
477 return false;
478}
479
480void FlexBuffersImpl::flush() {
481 ALOGV("[%s] buffers are flushed %zu", mName, mBuffers.size());
482 mBuffers.clear();
483}
484
Wonsik Kim0487b782020-10-28 11:45:50 -0700485size_t FlexBuffersImpl::numActiveSlots() const {
Wonsik Kim469c8342019-04-11 16:46:09 -0700486 return std::count_if(
487 mBuffers.begin(), mBuffers.end(),
488 [](const Entry &entry) {
Wonsik Kim0487b782020-10-28 11:45:50 -0700489 return (entry.clientBuffer != nullptr
490 || !entry.compBuffer.expired());
Wonsik Kim469c8342019-04-11 16:46:09 -0700491 });
492}
493
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700494size_t FlexBuffersImpl::numComponentBuffers() const {
495 return std::count_if(
496 mBuffers.begin(), mBuffers.end(),
497 [](const Entry &entry) {
498 return !entry.compBuffer.expired();
499 });
500}
501
Wonsik Kim469c8342019-04-11 16:46:09 -0700502// BuffersArrayImpl
503
504void BuffersArrayImpl::initialize(
505 const FlexBuffersImpl &impl,
506 size_t minSize,
507 std::function<sp<Codec2Buffer>()> allocate) {
508 mImplName = impl.mImplName + "[N]";
509 mName = mImplName.c_str();
510 for (size_t i = 0; i < impl.mBuffers.size(); ++i) {
511 sp<Codec2Buffer> clientBuffer = impl.mBuffers[i].clientBuffer;
512 bool ownedByClient = (clientBuffer != nullptr);
513 if (!ownedByClient) {
514 clientBuffer = allocate();
515 }
516 mBuffers.push_back({ clientBuffer, impl.mBuffers[i].compBuffer, ownedByClient });
517 }
518 ALOGV("[%s] converted %zu buffers to array mode of %zu", mName, mBuffers.size(), minSize);
519 for (size_t i = impl.mBuffers.size(); i < minSize; ++i) {
520 mBuffers.push_back({ allocate(), std::weak_ptr<C2Buffer>(), false });
521 }
522}
523
524status_t BuffersArrayImpl::grabBuffer(
525 size_t *index,
526 sp<Codec2Buffer> *buffer,
527 std::function<bool(const sp<Codec2Buffer> &)> match) {
528 // allBuffersDontMatch remains true if all buffers are available but
529 // match() returns false for every buffer.
530 bool allBuffersDontMatch = true;
531 for (size_t i = 0; i < mBuffers.size(); ++i) {
532 if (!mBuffers[i].ownedByClient && mBuffers[i].compBuffer.expired()) {
533 if (match(mBuffers[i].clientBuffer)) {
534 mBuffers[i].ownedByClient = true;
535 *buffer = mBuffers[i].clientBuffer;
536 (*buffer)->meta()->clear();
537 (*buffer)->setRange(0, (*buffer)->capacity());
538 *index = i;
539 return OK;
540 }
541 } else {
542 allBuffersDontMatch = false;
543 }
544 }
545 return allBuffersDontMatch ? NO_MEMORY : WOULD_BLOCK;
546}
547
548bool BuffersArrayImpl::returnBuffer(
549 const sp<MediaCodecBuffer> &buffer,
550 std::shared_ptr<C2Buffer> *c2buffer,
551 bool release) {
552 sp<Codec2Buffer> clientBuffer;
553 size_t index = mBuffers.size();
554 for (size_t i = 0; i < mBuffers.size(); ++i) {
555 if (mBuffers[i].clientBuffer == buffer) {
556 if (!mBuffers[i].ownedByClient) {
557 ALOGD("[%s] Client returned a buffer it does not own according to our record: %zu",
558 mName, i);
559 }
560 clientBuffer = mBuffers[i].clientBuffer;
561 if (release) {
562 mBuffers[i].ownedByClient = false;
563 }
564 index = i;
565 break;
566 }
567 }
568 if (clientBuffer == nullptr) {
569 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
570 return false;
571 }
572 ALOGV("[%s] %s: matching buffer found (index=%zu)", mName, __func__, index);
573 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
574 if (!result) {
575 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700576 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700577 mBuffers[index].compBuffer = result;
578 }
579 if (c2buffer) {
580 *c2buffer = result;
581 }
582 return true;
583}
584
585bool BuffersArrayImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
586 for (size_t i = 0; i < mBuffers.size(); ++i) {
587 std::shared_ptr<C2Buffer> compBuffer =
588 mBuffers[i].compBuffer.lock();
589 if (!compBuffer) {
590 continue;
591 }
592 if (c2buffer == compBuffer) {
593 if (mBuffers[i].ownedByClient) {
594 // This should not happen.
595 ALOGD("[%s] codec released a buffer owned by client "
596 "(index %zu)", mName, i);
597 }
598 mBuffers[i].compBuffer.reset();
599 ALOGV("[%s] codec released buffer #%zu(array mode)", mName, i);
600 return true;
601 }
602 }
603 ALOGV("[%s] codec released an unknown buffer (array mode)", mName);
604 return false;
605}
606
607void BuffersArrayImpl::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
608 array->clear();
609 for (const Entry &entry : mBuffers) {
610 array->push(entry.clientBuffer);
611 }
612}
613
614void BuffersArrayImpl::flush() {
615 for (Entry &entry : mBuffers) {
616 entry.ownedByClient = false;
617 }
618}
619
620void BuffersArrayImpl::realloc(std::function<sp<Codec2Buffer>()> alloc) {
621 size_t size = mBuffers.size();
622 mBuffers.clear();
623 for (size_t i = 0; i < size; ++i) {
624 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
625 }
626}
627
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700628void BuffersArrayImpl::grow(
629 size_t newSize, std::function<sp<Codec2Buffer>()> alloc) {
630 CHECK_LT(mBuffers.size(), newSize);
631 while (mBuffers.size() < newSize) {
632 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
633 }
634}
635
Wonsik Kim0487b782020-10-28 11:45:50 -0700636size_t BuffersArrayImpl::numActiveSlots() const {
Wonsik Kim469c8342019-04-11 16:46:09 -0700637 return std::count_if(
638 mBuffers.begin(), mBuffers.end(),
639 [](const Entry &entry) {
Wonsik Kim0487b782020-10-28 11:45:50 -0700640 return entry.ownedByClient || !entry.compBuffer.expired();
Wonsik Kim469c8342019-04-11 16:46:09 -0700641 });
642}
643
Wonsik Kima39882b2019-06-20 16:13:56 -0700644size_t BuffersArrayImpl::arraySize() const {
645 return mBuffers.size();
646}
647
Wonsik Kim469c8342019-04-11 16:46:09 -0700648// InputBuffersArray
649
650void InputBuffersArray::initialize(
651 const FlexBuffersImpl &impl,
652 size_t minSize,
653 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700654 mAllocate = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -0700655 mImpl.initialize(impl, minSize, allocate);
656}
657
658void InputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
659 mImpl.getArray(array);
660}
661
662bool InputBuffersArray::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
663 sp<Codec2Buffer> c2Buffer;
664 status_t err = mImpl.grabBuffer(index, &c2Buffer);
665 if (err == OK) {
666 c2Buffer->setFormat(mFormat);
667 handleImageData(c2Buffer);
668 *buffer = c2Buffer;
669 return true;
670 }
671 return false;
672}
673
674bool InputBuffersArray::releaseBuffer(
675 const sp<MediaCodecBuffer> &buffer,
676 std::shared_ptr<C2Buffer> *c2buffer,
677 bool release) {
678 return mImpl.returnBuffer(buffer, c2buffer, release);
679}
680
681bool InputBuffersArray::expireComponentBuffer(
682 const std::shared_ptr<C2Buffer> &c2buffer) {
683 return mImpl.expireComponentBuffer(c2buffer);
684}
685
686void InputBuffersArray::flush() {
687 mImpl.flush();
688}
689
Wonsik Kim0487b782020-10-28 11:45:50 -0700690size_t InputBuffersArray::numActiveSlots() const {
691 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700692}
693
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700694sp<Codec2Buffer> InputBuffersArray::createNewBuffer() {
695 return mAllocate();
696}
697
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800698// SlotInputBuffers
699
700bool SlotInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
701 sp<Codec2Buffer> newBuffer = createNewBuffer();
702 *index = mImpl.assignSlot(newBuffer);
703 *buffer = newBuffer;
704 return true;
705}
706
707bool SlotInputBuffers::releaseBuffer(
708 const sp<MediaCodecBuffer> &buffer,
709 std::shared_ptr<C2Buffer> *c2buffer,
710 bool release) {
711 return mImpl.releaseSlot(buffer, c2buffer, release);
712}
713
714bool SlotInputBuffers::expireComponentBuffer(
715 const std::shared_ptr<C2Buffer> &c2buffer) {
716 return mImpl.expireComponentBuffer(c2buffer);
717}
718
719void SlotInputBuffers::flush() {
720 mImpl.flush();
721}
722
723std::unique_ptr<InputBuffers> SlotInputBuffers::toArrayMode(size_t) {
724 TRESPASS("Array mode should not be called at non-legacy mode");
725 return nullptr;
726}
727
Wonsik Kim0487b782020-10-28 11:45:50 -0700728size_t SlotInputBuffers::numActiveSlots() const {
729 return mImpl.numActiveSlots();
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800730}
731
732sp<Codec2Buffer> SlotInputBuffers::createNewBuffer() {
733 return new DummyContainerBuffer{mFormat, nullptr};
734}
735
Wonsik Kim469c8342019-04-11 16:46:09 -0700736// LinearInputBuffers
737
738bool LinearInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700739 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700740 if (newBuffer == nullptr) {
741 return false;
742 }
743 *index = mImpl.assignSlot(newBuffer);
744 *buffer = newBuffer;
745 return true;
746}
747
748bool LinearInputBuffers::releaseBuffer(
749 const sp<MediaCodecBuffer> &buffer,
750 std::shared_ptr<C2Buffer> *c2buffer,
751 bool release) {
752 return mImpl.releaseSlot(buffer, c2buffer, release);
753}
754
755bool LinearInputBuffers::expireComponentBuffer(
756 const std::shared_ptr<C2Buffer> &c2buffer) {
757 return mImpl.expireComponentBuffer(c2buffer);
758}
759
760void LinearInputBuffers::flush() {
761 // This is no-op by default unless we're in array mode where we need to keep
762 // track of the flushed work.
763 mImpl.flush();
764}
765
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700766std::unique_ptr<InputBuffers> LinearInputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700767 std::unique_ptr<InputBuffersArray> array(
768 new InputBuffersArray(mComponentName.c_str(), "1D-Input[N]"));
769 array->setPool(mPool);
770 array->setFormat(mFormat);
771 array->initialize(
772 mImpl,
773 size,
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700774 [pool = mPool, format = mFormat] () -> sp<Codec2Buffer> {
775 return Alloc(pool, format);
776 });
Wonsik Kim469c8342019-04-11 16:46:09 -0700777 return std::move(array);
778}
779
Wonsik Kim0487b782020-10-28 11:45:50 -0700780size_t LinearInputBuffers::numActiveSlots() const {
781 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700782}
783
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700784// static
785sp<Codec2Buffer> LinearInputBuffers::Alloc(
786 const std::shared_ptr<C2BlockPool> &pool, const sp<AMessage> &format) {
787 int32_t capacity = kLinearBufferSize;
788 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
789 if ((size_t)capacity > kMaxLinearBufferSize) {
790 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
791 capacity = kMaxLinearBufferSize;
792 }
793
794 // TODO: read usage from intf
Wonsik Kim469c8342019-04-11 16:46:09 -0700795 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
796 std::shared_ptr<C2LinearBlock> block;
797
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700798 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700799 if (err != C2_OK) {
800 return nullptr;
801 }
802
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700803 return LinearBlockBuffer::Allocate(format, block);
804}
805
806sp<Codec2Buffer> LinearInputBuffers::createNewBuffer() {
807 return Alloc(mPool, mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -0700808}
809
810// EncryptedLinearInputBuffers
811
812EncryptedLinearInputBuffers::EncryptedLinearInputBuffers(
813 bool secure,
814 const sp<MemoryDealer> &dealer,
815 const sp<ICrypto> &crypto,
816 int32_t heapSeqNum,
817 size_t capacity,
818 size_t numInputSlots,
819 const char *componentName, const char *name)
820 : LinearInputBuffers(componentName, name),
821 mUsage({0, 0}),
822 mDealer(dealer),
823 mCrypto(crypto),
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700824 mMemoryVector(new std::vector<Entry>){
Wonsik Kim469c8342019-04-11 16:46:09 -0700825 if (secure) {
826 mUsage = { C2MemoryUsage::READ_PROTECTED, 0 };
827 } else {
828 mUsage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
829 }
830 for (size_t i = 0; i < numInputSlots; ++i) {
831 sp<IMemory> memory = mDealer->allocate(capacity);
832 if (memory == nullptr) {
833 ALOGD("[%s] Failed to allocate memory from dealer: only %zu slots allocated",
834 mName, i);
835 break;
836 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700837 mMemoryVector->push_back({std::weak_ptr<C2LinearBlock>(), memory, heapSeqNum});
Wonsik Kim469c8342019-04-11 16:46:09 -0700838 }
839}
840
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700841std::unique_ptr<InputBuffers> EncryptedLinearInputBuffers::toArrayMode(size_t size) {
842 std::unique_ptr<InputBuffersArray> array(
843 new InputBuffersArray(mComponentName.c_str(), "1D-EncryptedInput[N]"));
844 array->setPool(mPool);
845 array->setFormat(mFormat);
846 array->initialize(
847 mImpl,
848 size,
849 [pool = mPool,
850 format = mFormat,
851 usage = mUsage,
852 memoryVector = mMemoryVector] () -> sp<Codec2Buffer> {
853 return Alloc(pool, format, usage, memoryVector);
854 });
855 return std::move(array);
856}
857
858
859// static
860sp<Codec2Buffer> EncryptedLinearInputBuffers::Alloc(
861 const std::shared_ptr<C2BlockPool> &pool,
862 const sp<AMessage> &format,
863 C2MemoryUsage usage,
864 const std::shared_ptr<std::vector<EncryptedLinearInputBuffers::Entry>> &memoryVector) {
865 int32_t capacity = kLinearBufferSize;
866 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
867 if ((size_t)capacity > kMaxLinearBufferSize) {
868 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
869 capacity = kMaxLinearBufferSize;
870 }
871
Wonsik Kim469c8342019-04-11 16:46:09 -0700872 sp<IMemory> memory;
873 size_t slot = 0;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700874 int32_t heapSeqNum = -1;
875 for (; slot < memoryVector->size(); ++slot) {
876 if (memoryVector->at(slot).block.expired()) {
877 memory = memoryVector->at(slot).memory;
878 heapSeqNum = memoryVector->at(slot).heapSeqNum;
Wonsik Kim469c8342019-04-11 16:46:09 -0700879 break;
880 }
881 }
882 if (memory == nullptr) {
883 return nullptr;
884 }
885
886 std::shared_ptr<C2LinearBlock> block;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700887 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700888 if (err != C2_OK || block == nullptr) {
889 return nullptr;
890 }
891
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700892 memoryVector->at(slot).block = block;
893 return new EncryptedLinearBlockBuffer(format, block, memory, heapSeqNum);
894}
895
896sp<Codec2Buffer> EncryptedLinearInputBuffers::createNewBuffer() {
897 // TODO: android_2020
898 return nullptr;
Wonsik Kim469c8342019-04-11 16:46:09 -0700899}
900
901// GraphicMetadataInputBuffers
902
903GraphicMetadataInputBuffers::GraphicMetadataInputBuffers(
904 const char *componentName, const char *name)
905 : InputBuffers(componentName, name),
906 mImpl(mName),
907 mStore(GetCodec2PlatformAllocatorStore()) { }
908
909bool GraphicMetadataInputBuffers::requestNewBuffer(
910 size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700911 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700912 if (newBuffer == nullptr) {
913 return false;
914 }
915 *index = mImpl.assignSlot(newBuffer);
916 *buffer = newBuffer;
917 return true;
918}
919
920bool GraphicMetadataInputBuffers::releaseBuffer(
921 const sp<MediaCodecBuffer> &buffer,
922 std::shared_ptr<C2Buffer> *c2buffer,
923 bool release) {
924 return mImpl.releaseSlot(buffer, c2buffer, release);
925}
926
927bool GraphicMetadataInputBuffers::expireComponentBuffer(
928 const std::shared_ptr<C2Buffer> &c2buffer) {
929 return mImpl.expireComponentBuffer(c2buffer);
930}
931
932void GraphicMetadataInputBuffers::flush() {
933 // This is no-op by default unless we're in array mode where we need to keep
934 // track of the flushed work.
935}
936
937std::unique_ptr<InputBuffers> GraphicMetadataInputBuffers::toArrayMode(
938 size_t size) {
939 std::shared_ptr<C2Allocator> alloc;
940 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
941 if (err != C2_OK) {
942 return nullptr;
943 }
944 std::unique_ptr<InputBuffersArray> array(
945 new InputBuffersArray(mComponentName.c_str(), "2D-MetaInput[N]"));
946 array->setPool(mPool);
947 array->setFormat(mFormat);
948 array->initialize(
949 mImpl,
950 size,
951 [format = mFormat, alloc]() -> sp<Codec2Buffer> {
952 return new GraphicMetadataBuffer(format, alloc);
953 });
954 return std::move(array);
955}
956
Wonsik Kim0487b782020-10-28 11:45:50 -0700957size_t GraphicMetadataInputBuffers::numActiveSlots() const {
958 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700959}
960
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700961sp<Codec2Buffer> GraphicMetadataInputBuffers::createNewBuffer() {
962 std::shared_ptr<C2Allocator> alloc;
963 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
964 if (err != C2_OK) {
965 return nullptr;
966 }
967 return new GraphicMetadataBuffer(mFormat, alloc);
968}
969
Wonsik Kim469c8342019-04-11 16:46:09 -0700970// GraphicInputBuffers
971
972GraphicInputBuffers::GraphicInputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -0700973 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -0700974 : InputBuffers(componentName, name),
975 mImpl(mName),
Wonsik Kim41d83432020-04-27 16:40:49 -0700976 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -0700977
978bool GraphicInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700979 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700980 if (newBuffer == nullptr) {
981 return false;
982 }
983 *index = mImpl.assignSlot(newBuffer);
984 handleImageData(newBuffer);
985 *buffer = newBuffer;
986 return true;
987}
988
989bool GraphicInputBuffers::releaseBuffer(
990 const sp<MediaCodecBuffer> &buffer,
991 std::shared_ptr<C2Buffer> *c2buffer,
992 bool release) {
993 return mImpl.releaseSlot(buffer, c2buffer, release);
994}
995
996bool GraphicInputBuffers::expireComponentBuffer(
997 const std::shared_ptr<C2Buffer> &c2buffer) {
998 return mImpl.expireComponentBuffer(c2buffer);
999}
1000
1001void GraphicInputBuffers::flush() {
1002 // This is no-op by default unless we're in array mode where we need to keep
1003 // track of the flushed work.
1004}
1005
1006std::unique_ptr<InputBuffers> GraphicInputBuffers::toArrayMode(size_t size) {
1007 std::unique_ptr<InputBuffersArray> array(
1008 new InputBuffersArray(mComponentName.c_str(), "2D-BB-Input[N]"));
1009 array->setPool(mPool);
1010 array->setFormat(mFormat);
1011 array->initialize(
1012 mImpl,
1013 size,
1014 [pool = mPool, format = mFormat, lbp = mLocalBufferPool]() -> sp<Codec2Buffer> {
1015 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
1016 return AllocateGraphicBuffer(
1017 pool, format, HAL_PIXEL_FORMAT_YV12, usage, lbp);
1018 });
1019 return std::move(array);
1020}
1021
Wonsik Kim0487b782020-10-28 11:45:50 -07001022size_t GraphicInputBuffers::numActiveSlots() const {
1023 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001024}
1025
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001026sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
1027 // TODO: read usage from intf
1028 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
1029 return AllocateGraphicBuffer(
1030 mPool, mFormat, HAL_PIXEL_FORMAT_YV12, usage, mLocalBufferPool);
1031}
1032
Wonsik Kim469c8342019-04-11 16:46:09 -07001033// OutputBuffersArray
1034
1035void OutputBuffersArray::initialize(
1036 const FlexBuffersImpl &impl,
1037 size_t minSize,
1038 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001039 mAlloc = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -07001040 mImpl.initialize(impl, minSize, allocate);
1041}
1042
1043status_t OutputBuffersArray::registerBuffer(
1044 const std::shared_ptr<C2Buffer> &buffer,
1045 size_t *index,
1046 sp<MediaCodecBuffer> *clientBuffer) {
1047 sp<Codec2Buffer> c2Buffer;
1048 status_t err = mImpl.grabBuffer(
1049 index,
1050 &c2Buffer,
1051 [buffer](const sp<Codec2Buffer> &clientBuffer) {
1052 return clientBuffer->canCopy(buffer);
1053 });
1054 if (err == WOULD_BLOCK) {
1055 ALOGV("[%s] buffers temporarily not available", mName);
1056 return err;
1057 } else if (err != OK) {
1058 ALOGD("[%s] grabBuffer failed: %d", mName, err);
1059 return err;
1060 }
1061 c2Buffer->setFormat(mFormat);
1062 if (!c2Buffer->copy(buffer)) {
1063 ALOGD("[%s] copy buffer failed", mName);
1064 return WOULD_BLOCK;
1065 }
1066 submit(c2Buffer);
1067 handleImageData(c2Buffer);
1068 *clientBuffer = c2Buffer;
1069 ALOGV("[%s] grabbed buffer %zu", mName, *index);
1070 return OK;
1071}
1072
1073status_t OutputBuffersArray::registerCsd(
1074 const C2StreamInitDataInfo::output *csd,
1075 size_t *index,
1076 sp<MediaCodecBuffer> *clientBuffer) {
1077 sp<Codec2Buffer> c2Buffer;
1078 status_t err = mImpl.grabBuffer(
1079 index,
1080 &c2Buffer,
1081 [csd](const sp<Codec2Buffer> &clientBuffer) {
1082 return clientBuffer->base() != nullptr
1083 && clientBuffer->capacity() >= csd->flexCount();
1084 });
1085 if (err != OK) {
1086 return err;
1087 }
1088 memcpy(c2Buffer->base(), csd->m.value, csd->flexCount());
1089 c2Buffer->setRange(0, csd->flexCount());
1090 c2Buffer->setFormat(mFormat);
1091 *clientBuffer = c2Buffer;
1092 return OK;
1093}
1094
1095bool OutputBuffersArray::releaseBuffer(
1096 const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) {
1097 return mImpl.returnBuffer(buffer, c2buffer, true);
1098}
1099
1100void OutputBuffersArray::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1101 (void)flushedWork;
1102 mImpl.flush();
1103 if (mSkipCutBuffer != nullptr) {
1104 mSkipCutBuffer->clear();
1105 }
1106}
1107
1108void OutputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
1109 mImpl.getArray(array);
1110}
1111
Wonsik Kim0487b782020-10-28 11:45:50 -07001112size_t OutputBuffersArray::numActiveSlots() const {
1113 return mImpl.numActiveSlots();
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001114}
1115
Wonsik Kim469c8342019-04-11 16:46:09 -07001116void OutputBuffersArray::realloc(const std::shared_ptr<C2Buffer> &c2buffer) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001117 switch (c2buffer->data().type()) {
1118 case C2BufferData::LINEAR: {
1119 uint32_t size = kLinearBufferSize;
Nick Desaulniersd09eaea2019-10-07 20:19:39 -07001120 const std::vector<C2ConstLinearBlock> &linear_blocks = c2buffer->data().linearBlocks();
1121 const uint32_t block_size = linear_blocks.front().size();
1122 if (block_size < kMaxLinearBufferSize / 2) {
1123 size = block_size * 2;
Wonsik Kim469c8342019-04-11 16:46:09 -07001124 } else {
1125 size = kMaxLinearBufferSize;
1126 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001127 mAlloc = [format = mFormat, size] {
Wonsik Kim469c8342019-04-11 16:46:09 -07001128 return new LocalLinearBuffer(format, new ABuffer(size));
1129 };
Wonsik Kima39882b2019-06-20 16:13:56 -07001130 ALOGD("[%s] reallocating with linear buffer of size %u", mName, size);
Wonsik Kim469c8342019-04-11 16:46:09 -07001131 break;
1132 }
1133
Wonsik Kima39882b2019-06-20 16:13:56 -07001134 case C2BufferData::GRAPHIC: {
1135 // This is only called for RawGraphicOutputBuffers.
1136 mAlloc = [format = mFormat,
Wonsik Kim41d83432020-04-27 16:40:49 -07001137 lbp = LocalBufferPool::Create()] {
Wonsik Kima39882b2019-06-20 16:13:56 -07001138 return ConstGraphicBlockBuffer::AllocateEmpty(
1139 format,
1140 [lbp](size_t capacity) {
1141 return lbp->newBuffer(capacity);
1142 });
1143 };
1144 ALOGD("[%s] reallocating with graphic buffer: format = %s",
1145 mName, mFormat->debugString().c_str());
1146 break;
1147 }
Wonsik Kim469c8342019-04-11 16:46:09 -07001148
1149 case C2BufferData::INVALID: [[fallthrough]];
1150 case C2BufferData::LINEAR_CHUNKS: [[fallthrough]];
1151 case C2BufferData::GRAPHIC_CHUNKS: [[fallthrough]];
1152 default:
1153 ALOGD("Unsupported type: %d", (int)c2buffer->data().type());
1154 return;
1155 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001156 mImpl.realloc(mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -07001157}
1158
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001159void OutputBuffersArray::grow(size_t newSize) {
1160 mImpl.grow(newSize, mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -07001161}
1162
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001163void OutputBuffersArray::transferFrom(OutputBuffers* source) {
1164 mFormat = source->mFormat;
1165 mSkipCutBuffer = source->mSkipCutBuffer;
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001166 mPending = std::move(source->mPending);
1167 mReorderStash = std::move(source->mReorderStash);
1168 mDepth = source->mDepth;
1169 mKey = source->mKey;
1170}
1171
Wonsik Kim469c8342019-04-11 16:46:09 -07001172// FlexOutputBuffers
1173
1174status_t FlexOutputBuffers::registerBuffer(
1175 const std::shared_ptr<C2Buffer> &buffer,
1176 size_t *index,
1177 sp<MediaCodecBuffer> *clientBuffer) {
1178 sp<Codec2Buffer> newBuffer = wrap(buffer);
1179 if (newBuffer == nullptr) {
1180 return NO_MEMORY;
1181 }
1182 newBuffer->setFormat(mFormat);
1183 *index = mImpl.assignSlot(newBuffer);
1184 handleImageData(newBuffer);
1185 *clientBuffer = newBuffer;
1186 ALOGV("[%s] registered buffer %zu", mName, *index);
1187 return OK;
1188}
1189
1190status_t FlexOutputBuffers::registerCsd(
1191 const C2StreamInitDataInfo::output *csd,
1192 size_t *index,
1193 sp<MediaCodecBuffer> *clientBuffer) {
1194 sp<Codec2Buffer> newBuffer = new LocalLinearBuffer(
1195 mFormat, ABuffer::CreateAsCopy(csd->m.value, csd->flexCount()));
1196 *index = mImpl.assignSlot(newBuffer);
1197 *clientBuffer = newBuffer;
1198 return OK;
1199}
1200
1201bool FlexOutputBuffers::releaseBuffer(
1202 const sp<MediaCodecBuffer> &buffer,
1203 std::shared_ptr<C2Buffer> *c2buffer) {
1204 return mImpl.releaseSlot(buffer, c2buffer, true);
1205}
1206
1207void FlexOutputBuffers::flush(
1208 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1209 (void) flushedWork;
1210 // This is no-op by default unless we're in array mode where we need to keep
1211 // track of the flushed work.
1212}
1213
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001214std::unique_ptr<OutputBuffersArray> FlexOutputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001215 std::unique_ptr<OutputBuffersArray> array(new OutputBuffersArray(mComponentName.c_str()));
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001216 array->transferFrom(this);
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001217 std::function<sp<Codec2Buffer>()> alloc = getAlloc();
1218 array->initialize(mImpl, size, alloc);
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001219 return array;
Wonsik Kim469c8342019-04-11 16:46:09 -07001220}
1221
Wonsik Kim0487b782020-10-28 11:45:50 -07001222size_t FlexOutputBuffers::numActiveSlots() const {
1223 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001224}
1225
1226// LinearOutputBuffers
1227
1228void LinearOutputBuffers::flush(
1229 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1230 if (mSkipCutBuffer != nullptr) {
1231 mSkipCutBuffer->clear();
1232 }
1233 FlexOutputBuffers::flush(flushedWork);
1234}
1235
1236sp<Codec2Buffer> LinearOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1237 if (buffer == nullptr) {
1238 ALOGV("[%s] using a dummy buffer", mName);
1239 return new LocalLinearBuffer(mFormat, new ABuffer(0));
1240 }
1241 if (buffer->data().type() != C2BufferData::LINEAR) {
1242 ALOGV("[%s] non-linear buffer %d", mName, buffer->data().type());
1243 // We expect linear output buffers from the component.
1244 return nullptr;
1245 }
1246 if (buffer->data().linearBlocks().size() != 1u) {
1247 ALOGV("[%s] no linear buffers", mName);
1248 // We expect one and only one linear block from the component.
1249 return nullptr;
1250 }
1251 sp<Codec2Buffer> clientBuffer = ConstLinearBlockBuffer::Allocate(mFormat, buffer);
1252 if (clientBuffer == nullptr) {
1253 ALOGD("[%s] ConstLinearBlockBuffer::Allocate failed", mName);
1254 return nullptr;
1255 }
1256 submit(clientBuffer);
1257 return clientBuffer;
1258}
1259
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001260std::function<sp<Codec2Buffer>()> LinearOutputBuffers::getAlloc() {
1261 return [format = mFormat]{
1262 // TODO: proper max output size
1263 return new LocalLinearBuffer(format, new ABuffer(kLinearBufferSize));
1264 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001265}
1266
1267// GraphicOutputBuffers
1268
1269sp<Codec2Buffer> GraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1270 return new DummyContainerBuffer(mFormat, buffer);
1271}
1272
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001273std::function<sp<Codec2Buffer>()> GraphicOutputBuffers::getAlloc() {
1274 return [format = mFormat]{
1275 return new DummyContainerBuffer(format);
1276 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001277}
1278
1279// RawGraphicOutputBuffers
1280
1281RawGraphicOutputBuffers::RawGraphicOutputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -07001282 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -07001283 : FlexOutputBuffers(componentName, name),
Wonsik Kim41d83432020-04-27 16:40:49 -07001284 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -07001285
1286sp<Codec2Buffer> RawGraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1287 if (buffer == nullptr) {
1288 sp<Codec2Buffer> c2buffer = ConstGraphicBlockBuffer::AllocateEmpty(
1289 mFormat,
1290 [lbp = mLocalBufferPool](size_t capacity) {
1291 return lbp->newBuffer(capacity);
1292 });
1293 if (c2buffer == nullptr) {
1294 ALOGD("[%s] ConstGraphicBlockBuffer::AllocateEmpty failed", mName);
1295 return nullptr;
1296 }
1297 c2buffer->setRange(0, 0);
1298 return c2buffer;
1299 } else {
1300 return ConstGraphicBlockBuffer::Allocate(
1301 mFormat,
1302 buffer,
1303 [lbp = mLocalBufferPool](size_t capacity) {
1304 return lbp->newBuffer(capacity);
1305 });
1306 }
1307}
1308
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001309std::function<sp<Codec2Buffer>()> RawGraphicOutputBuffers::getAlloc() {
1310 return [format = mFormat, lbp = mLocalBufferPool]{
1311 return ConstGraphicBlockBuffer::AllocateEmpty(
1312 format,
1313 [lbp](size_t capacity) {
1314 return lbp->newBuffer(capacity);
1315 });
1316 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001317}
1318
1319} // namespace android