blob: caa826b2165b18fdb154a8bc955fff5bfd242d8a [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>
24#include <media/stagefright/MediaCodecConstants.h>
Wonsik Kim155d5cb2019-10-09 12:49:49 -070025#include <media/stagefright/SkipCutBuffer.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070026#include <mediadrm/ICrypto.h>
Wonsik Kim469c8342019-04-11 16:46:09 -070027
28#include "CCodecBuffers.h"
29
30namespace android {
31
32namespace {
33
34sp<GraphicBlockBuffer> AllocateGraphicBuffer(
35 const std::shared_ptr<C2BlockPool> &pool,
36 const sp<AMessage> &format,
37 uint32_t pixelFormat,
38 const C2MemoryUsage &usage,
39 const std::shared_ptr<LocalBufferPool> &localBufferPool) {
40 int32_t width, height;
41 if (!format->findInt32("width", &width) || !format->findInt32("height", &height)) {
42 ALOGD("format lacks width or height");
43 return nullptr;
44 }
45
46 std::shared_ptr<C2GraphicBlock> block;
47 c2_status_t err = pool->fetchGraphicBlock(
48 width, height, pixelFormat, usage, &block);
49 if (err != C2_OK) {
50 ALOGD("fetch graphic block failed: %d", err);
51 return nullptr;
52 }
53
54 return GraphicBlockBuffer::Allocate(
55 format,
56 block,
57 [localBufferPool](size_t capacity) {
58 return localBufferPool->newBuffer(capacity);
59 });
60}
61
62} // namespace
63
64// CCodecBuffers
65
66void CCodecBuffers::setFormat(const sp<AMessage> &format) {
67 CHECK(format != nullptr);
68 mFormat = format;
69}
70
71sp<AMessage> CCodecBuffers::dupFormat() {
72 return mFormat != nullptr ? mFormat->dup() : nullptr;
73}
74
75void CCodecBuffers::handleImageData(const sp<Codec2Buffer> &buffer) {
76 sp<ABuffer> imageDataCandidate = buffer->getImageData();
77 if (imageDataCandidate == nullptr) {
78 return;
79 }
80 sp<ABuffer> imageData;
81 if (!mFormat->findBuffer("image-data", &imageData)
82 || imageDataCandidate->size() != imageData->size()
83 || memcmp(imageDataCandidate->data(), imageData->data(), imageData->size()) != 0) {
84 ALOGD("[%s] updating image-data", mName);
85 sp<AMessage> newFormat = dupFormat();
86 newFormat->setBuffer("image-data", imageDataCandidate);
87 MediaImage2 *img = (MediaImage2*)imageDataCandidate->data();
88 if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
89 int32_t stride = img->mPlane[0].mRowInc;
90 newFormat->setInt32(KEY_STRIDE, stride);
91 ALOGD("[%s] updating stride = %d", mName, stride);
92 if (img->mNumPlanes > 1 && stride > 0) {
93 int32_t vstride = (img->mPlane[1].mOffset - img->mPlane[0].mOffset) / stride;
94 newFormat->setInt32(KEY_SLICE_HEIGHT, vstride);
95 ALOGD("[%s] updating vstride = %d", mName, vstride);
96 }
97 }
98 setFormat(newFormat);
99 buffer->setFormat(newFormat);
100 }
101}
102
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700103// InputBuffers
104
105sp<Codec2Buffer> InputBuffers::cloneAndReleaseBuffer(const sp<MediaCodecBuffer> &buffer) {
106 sp<Codec2Buffer> copy = createNewBuffer();
107 if (copy == nullptr) {
108 return nullptr;
109 }
110 std::shared_ptr<C2Buffer> c2buffer;
111 if (!releaseBuffer(buffer, &c2buffer, true)) {
112 return nullptr;
113 }
114 if (!copy->canCopy(c2buffer)) {
115 return nullptr;
116 }
117 if (!copy->copy(c2buffer)) {
118 return nullptr;
119 }
120 return copy;
121}
122
Wonsik Kim469c8342019-04-11 16:46:09 -0700123// OutputBuffers
124
Wonsik Kim41d83432020-04-27 16:40:49 -0700125OutputBuffers::OutputBuffers(const char *componentName, const char *name)
126 : CCodecBuffers(componentName, name) { }
127
128OutputBuffers::~OutputBuffers() = default;
129
Wonsik Kim469c8342019-04-11 16:46:09 -0700130void OutputBuffers::initSkipCutBuffer(
131 int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount) {
132 CHECK(mSkipCutBuffer == nullptr);
133 mDelay = delay;
134 mPadding = padding;
135 mSampleRate = sampleRate;
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700136 mChannelCount = channelCount;
137 setSkipCutBuffer(delay, padding);
Wonsik Kim469c8342019-04-11 16:46:09 -0700138}
139
140void OutputBuffers::updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount) {
141 if (mSkipCutBuffer == nullptr) {
142 return;
143 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700144 if (mSampleRate == sampleRate && mChannelCount == channelCount) {
145 return;
146 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700147 int32_t delay = mDelay;
148 int32_t padding = mPadding;
149 if (sampleRate != mSampleRate) {
150 delay = ((int64_t)delay * sampleRate) / mSampleRate;
151 padding = ((int64_t)padding * sampleRate) / mSampleRate;
152 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700153 mSampleRate = sampleRate;
154 mChannelCount = channelCount;
155 setSkipCutBuffer(delay, padding);
Wonsik Kim469c8342019-04-11 16:46:09 -0700156}
157
158void OutputBuffers::submit(const sp<MediaCodecBuffer> &buffer) {
159 if (mSkipCutBuffer != nullptr) {
160 mSkipCutBuffer->submit(buffer);
161 }
162}
163
Wonsik Kima4e049d2020-04-28 19:42:23 +0000164void OutputBuffers::transferSkipCutBuffer(const sp<SkipCutBuffer> &scb) {
165 mSkipCutBuffer = scb;
166}
167
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700168void OutputBuffers::setSkipCutBuffer(int32_t skip, int32_t cut) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700169 if (mSkipCutBuffer != nullptr) {
170 size_t prevSize = mSkipCutBuffer->size();
171 if (prevSize != 0u) {
172 ALOGD("[%s] Replacing SkipCutBuffer holding %zu bytes", mName, prevSize);
173 }
174 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700175 mSkipCutBuffer = new SkipCutBuffer(skip, cut, mChannelCount);
Wonsik Kim469c8342019-04-11 16:46:09 -0700176}
177
178// LocalBufferPool
179
Wonsik Kim41d83432020-04-27 16:40:49 -0700180constexpr size_t kInitialPoolCapacity = kMaxLinearBufferSize;
181constexpr size_t kMaxPoolCapacity = kMaxLinearBufferSize * 32;
182
183std::shared_ptr<LocalBufferPool> LocalBufferPool::Create() {
184 return std::shared_ptr<LocalBufferPool>(new LocalBufferPool(kInitialPoolCapacity));
Wonsik Kim469c8342019-04-11 16:46:09 -0700185}
186
187sp<ABuffer> LocalBufferPool::newBuffer(size_t capacity) {
188 Mutex::Autolock lock(mMutex);
189 auto it = std::find_if(
190 mPool.begin(), mPool.end(),
191 [capacity](const std::vector<uint8_t> &vec) {
192 return vec.capacity() >= capacity;
193 });
194 if (it != mPool.end()) {
195 sp<ABuffer> buffer = new VectorBuffer(std::move(*it), shared_from_this());
196 mPool.erase(it);
197 return buffer;
198 }
199 if (mUsedSize + capacity > mPoolCapacity) {
200 while (!mPool.empty()) {
201 mUsedSize -= mPool.back().capacity();
202 mPool.pop_back();
203 }
Wonsik Kim41d83432020-04-27 16:40:49 -0700204 while (mUsedSize + capacity > mPoolCapacity && mPoolCapacity * 2 <= kMaxPoolCapacity) {
205 ALOGD("Increasing local buffer pool capacity from %zu to %zu",
206 mPoolCapacity, mPoolCapacity * 2);
207 mPoolCapacity *= 2;
208 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700209 if (mUsedSize + capacity > mPoolCapacity) {
210 ALOGD("mUsedSize = %zu, capacity = %zu, mPoolCapacity = %zu",
211 mUsedSize, capacity, mPoolCapacity);
212 return nullptr;
213 }
214 }
215 std::vector<uint8_t> vec(capacity);
216 mUsedSize += vec.capacity();
217 return new VectorBuffer(std::move(vec), shared_from_this());
218}
219
220LocalBufferPool::VectorBuffer::VectorBuffer(
221 std::vector<uint8_t> &&vec, const std::shared_ptr<LocalBufferPool> &pool)
222 : ABuffer(vec.data(), vec.capacity()),
223 mVec(std::move(vec)),
224 mPool(pool) {
225}
226
227LocalBufferPool::VectorBuffer::~VectorBuffer() {
228 std::shared_ptr<LocalBufferPool> pool = mPool.lock();
229 if (pool) {
230 // If pool is alive, return the vector back to the pool so that
231 // it can be recycled.
232 pool->returnVector(std::move(mVec));
233 }
234}
235
236void LocalBufferPool::returnVector(std::vector<uint8_t> &&vec) {
237 Mutex::Autolock lock(mMutex);
238 mPool.push_front(std::move(vec));
239}
240
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700241// FlexBuffersImpl
242
Wonsik Kim469c8342019-04-11 16:46:09 -0700243size_t FlexBuffersImpl::assignSlot(const sp<Codec2Buffer> &buffer) {
244 for (size_t i = 0; i < mBuffers.size(); ++i) {
245 if (mBuffers[i].clientBuffer == nullptr
246 && mBuffers[i].compBuffer.expired()) {
247 mBuffers[i].clientBuffer = buffer;
248 return i;
249 }
250 }
251 mBuffers.push_back({ buffer, std::weak_ptr<C2Buffer>() });
252 return mBuffers.size() - 1;
253}
254
Wonsik Kim469c8342019-04-11 16:46:09 -0700255bool FlexBuffersImpl::releaseSlot(
256 const sp<MediaCodecBuffer> &buffer,
257 std::shared_ptr<C2Buffer> *c2buffer,
258 bool release) {
259 sp<Codec2Buffer> clientBuffer;
260 size_t index = mBuffers.size();
261 for (size_t i = 0; i < mBuffers.size(); ++i) {
262 if (mBuffers[i].clientBuffer == buffer) {
263 clientBuffer = mBuffers[i].clientBuffer;
264 if (release) {
265 mBuffers[i].clientBuffer.clear();
266 }
267 index = i;
268 break;
269 }
270 }
271 if (clientBuffer == nullptr) {
272 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
273 return false;
274 }
275 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
276 if (!result) {
277 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700278 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700279 mBuffers[index].compBuffer = result;
280 }
281 if (c2buffer) {
282 *c2buffer = result;
283 }
284 return true;
285}
286
287bool FlexBuffersImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
288 for (size_t i = 0; i < mBuffers.size(); ++i) {
289 std::shared_ptr<C2Buffer> compBuffer =
290 mBuffers[i].compBuffer.lock();
291 if (!compBuffer || compBuffer != c2buffer) {
292 continue;
293 }
294 mBuffers[i].compBuffer.reset();
295 ALOGV("[%s] codec released buffer #%zu", mName, i);
296 return true;
297 }
298 ALOGV("[%s] codec released an unknown buffer", mName);
299 return false;
300}
301
302void FlexBuffersImpl::flush() {
303 ALOGV("[%s] buffers are flushed %zu", mName, mBuffers.size());
304 mBuffers.clear();
305}
306
307size_t FlexBuffersImpl::numClientBuffers() const {
308 return std::count_if(
309 mBuffers.begin(), mBuffers.end(),
310 [](const Entry &entry) {
311 return (entry.clientBuffer != nullptr);
312 });
313}
314
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700315size_t FlexBuffersImpl::numComponentBuffers() const {
316 return std::count_if(
317 mBuffers.begin(), mBuffers.end(),
318 [](const Entry &entry) {
319 return !entry.compBuffer.expired();
320 });
321}
322
Wonsik Kim469c8342019-04-11 16:46:09 -0700323// BuffersArrayImpl
324
325void BuffersArrayImpl::initialize(
326 const FlexBuffersImpl &impl,
327 size_t minSize,
328 std::function<sp<Codec2Buffer>()> allocate) {
329 mImplName = impl.mImplName + "[N]";
330 mName = mImplName.c_str();
331 for (size_t i = 0; i < impl.mBuffers.size(); ++i) {
332 sp<Codec2Buffer> clientBuffer = impl.mBuffers[i].clientBuffer;
333 bool ownedByClient = (clientBuffer != nullptr);
334 if (!ownedByClient) {
335 clientBuffer = allocate();
336 }
337 mBuffers.push_back({ clientBuffer, impl.mBuffers[i].compBuffer, ownedByClient });
338 }
339 ALOGV("[%s] converted %zu buffers to array mode of %zu", mName, mBuffers.size(), minSize);
340 for (size_t i = impl.mBuffers.size(); i < minSize; ++i) {
341 mBuffers.push_back({ allocate(), std::weak_ptr<C2Buffer>(), false });
342 }
343}
344
345status_t BuffersArrayImpl::grabBuffer(
346 size_t *index,
347 sp<Codec2Buffer> *buffer,
348 std::function<bool(const sp<Codec2Buffer> &)> match) {
349 // allBuffersDontMatch remains true if all buffers are available but
350 // match() returns false for every buffer.
351 bool allBuffersDontMatch = true;
352 for (size_t i = 0; i < mBuffers.size(); ++i) {
353 if (!mBuffers[i].ownedByClient && mBuffers[i].compBuffer.expired()) {
354 if (match(mBuffers[i].clientBuffer)) {
355 mBuffers[i].ownedByClient = true;
356 *buffer = mBuffers[i].clientBuffer;
357 (*buffer)->meta()->clear();
358 (*buffer)->setRange(0, (*buffer)->capacity());
359 *index = i;
360 return OK;
361 }
362 } else {
363 allBuffersDontMatch = false;
364 }
365 }
366 return allBuffersDontMatch ? NO_MEMORY : WOULD_BLOCK;
367}
368
369bool BuffersArrayImpl::returnBuffer(
370 const sp<MediaCodecBuffer> &buffer,
371 std::shared_ptr<C2Buffer> *c2buffer,
372 bool release) {
373 sp<Codec2Buffer> clientBuffer;
374 size_t index = mBuffers.size();
375 for (size_t i = 0; i < mBuffers.size(); ++i) {
376 if (mBuffers[i].clientBuffer == buffer) {
377 if (!mBuffers[i].ownedByClient) {
378 ALOGD("[%s] Client returned a buffer it does not own according to our record: %zu",
379 mName, i);
380 }
381 clientBuffer = mBuffers[i].clientBuffer;
382 if (release) {
383 mBuffers[i].ownedByClient = false;
384 }
385 index = i;
386 break;
387 }
388 }
389 if (clientBuffer == nullptr) {
390 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
391 return false;
392 }
393 ALOGV("[%s] %s: matching buffer found (index=%zu)", mName, __func__, index);
394 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
395 if (!result) {
396 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700397 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700398 mBuffers[index].compBuffer = result;
399 }
400 if (c2buffer) {
401 *c2buffer = result;
402 }
403 return true;
404}
405
406bool BuffersArrayImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
407 for (size_t i = 0; i < mBuffers.size(); ++i) {
408 std::shared_ptr<C2Buffer> compBuffer =
409 mBuffers[i].compBuffer.lock();
410 if (!compBuffer) {
411 continue;
412 }
413 if (c2buffer == compBuffer) {
414 if (mBuffers[i].ownedByClient) {
415 // This should not happen.
416 ALOGD("[%s] codec released a buffer owned by client "
417 "(index %zu)", mName, i);
418 }
419 mBuffers[i].compBuffer.reset();
420 ALOGV("[%s] codec released buffer #%zu(array mode)", mName, i);
421 return true;
422 }
423 }
424 ALOGV("[%s] codec released an unknown buffer (array mode)", mName);
425 return false;
426}
427
428void BuffersArrayImpl::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
429 array->clear();
430 for (const Entry &entry : mBuffers) {
431 array->push(entry.clientBuffer);
432 }
433}
434
435void BuffersArrayImpl::flush() {
436 for (Entry &entry : mBuffers) {
437 entry.ownedByClient = false;
438 }
439}
440
441void BuffersArrayImpl::realloc(std::function<sp<Codec2Buffer>()> alloc) {
442 size_t size = mBuffers.size();
443 mBuffers.clear();
444 for (size_t i = 0; i < size; ++i) {
445 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
446 }
447}
448
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700449void BuffersArrayImpl::grow(
450 size_t newSize, std::function<sp<Codec2Buffer>()> alloc) {
451 CHECK_LT(mBuffers.size(), newSize);
452 while (mBuffers.size() < newSize) {
453 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
454 }
455}
456
Wonsik Kim469c8342019-04-11 16:46:09 -0700457size_t BuffersArrayImpl::numClientBuffers() const {
458 return std::count_if(
459 mBuffers.begin(), mBuffers.end(),
460 [](const Entry &entry) {
461 return entry.ownedByClient;
462 });
463}
464
Wonsik Kima39882b2019-06-20 16:13:56 -0700465size_t BuffersArrayImpl::arraySize() const {
466 return mBuffers.size();
467}
468
Wonsik Kim469c8342019-04-11 16:46:09 -0700469// InputBuffersArray
470
471void InputBuffersArray::initialize(
472 const FlexBuffersImpl &impl,
473 size_t minSize,
474 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700475 mAllocate = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -0700476 mImpl.initialize(impl, minSize, allocate);
477}
478
479void InputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
480 mImpl.getArray(array);
481}
482
483bool InputBuffersArray::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
484 sp<Codec2Buffer> c2Buffer;
485 status_t err = mImpl.grabBuffer(index, &c2Buffer);
486 if (err == OK) {
487 c2Buffer->setFormat(mFormat);
488 handleImageData(c2Buffer);
489 *buffer = c2Buffer;
490 return true;
491 }
492 return false;
493}
494
495bool InputBuffersArray::releaseBuffer(
496 const sp<MediaCodecBuffer> &buffer,
497 std::shared_ptr<C2Buffer> *c2buffer,
498 bool release) {
499 return mImpl.returnBuffer(buffer, c2buffer, release);
500}
501
502bool InputBuffersArray::expireComponentBuffer(
503 const std::shared_ptr<C2Buffer> &c2buffer) {
504 return mImpl.expireComponentBuffer(c2buffer);
505}
506
507void InputBuffersArray::flush() {
508 mImpl.flush();
509}
510
511size_t InputBuffersArray::numClientBuffers() const {
512 return mImpl.numClientBuffers();
513}
514
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700515sp<Codec2Buffer> InputBuffersArray::createNewBuffer() {
516 return mAllocate();
517}
518
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800519// SlotInputBuffers
520
521bool SlotInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
522 sp<Codec2Buffer> newBuffer = createNewBuffer();
523 *index = mImpl.assignSlot(newBuffer);
524 *buffer = newBuffer;
525 return true;
526}
527
528bool SlotInputBuffers::releaseBuffer(
529 const sp<MediaCodecBuffer> &buffer,
530 std::shared_ptr<C2Buffer> *c2buffer,
531 bool release) {
532 return mImpl.releaseSlot(buffer, c2buffer, release);
533}
534
535bool SlotInputBuffers::expireComponentBuffer(
536 const std::shared_ptr<C2Buffer> &c2buffer) {
537 return mImpl.expireComponentBuffer(c2buffer);
538}
539
540void SlotInputBuffers::flush() {
541 mImpl.flush();
542}
543
544std::unique_ptr<InputBuffers> SlotInputBuffers::toArrayMode(size_t) {
545 TRESPASS("Array mode should not be called at non-legacy mode");
546 return nullptr;
547}
548
549size_t SlotInputBuffers::numClientBuffers() const {
550 return mImpl.numClientBuffers();
551}
552
553sp<Codec2Buffer> SlotInputBuffers::createNewBuffer() {
554 return new DummyContainerBuffer{mFormat, nullptr};
555}
556
Wonsik Kim469c8342019-04-11 16:46:09 -0700557// LinearInputBuffers
558
559bool LinearInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700560 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700561 if (newBuffer == nullptr) {
562 return false;
563 }
564 *index = mImpl.assignSlot(newBuffer);
565 *buffer = newBuffer;
566 return true;
567}
568
569bool LinearInputBuffers::releaseBuffer(
570 const sp<MediaCodecBuffer> &buffer,
571 std::shared_ptr<C2Buffer> *c2buffer,
572 bool release) {
573 return mImpl.releaseSlot(buffer, c2buffer, release);
574}
575
576bool LinearInputBuffers::expireComponentBuffer(
577 const std::shared_ptr<C2Buffer> &c2buffer) {
578 return mImpl.expireComponentBuffer(c2buffer);
579}
580
581void LinearInputBuffers::flush() {
582 // This is no-op by default unless we're in array mode where we need to keep
583 // track of the flushed work.
584 mImpl.flush();
585}
586
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700587std::unique_ptr<InputBuffers> LinearInputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700588 std::unique_ptr<InputBuffersArray> array(
589 new InputBuffersArray(mComponentName.c_str(), "1D-Input[N]"));
590 array->setPool(mPool);
591 array->setFormat(mFormat);
592 array->initialize(
593 mImpl,
594 size,
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700595 [pool = mPool, format = mFormat] () -> sp<Codec2Buffer> {
596 return Alloc(pool, format);
597 });
Wonsik Kim469c8342019-04-11 16:46:09 -0700598 return std::move(array);
599}
600
601size_t LinearInputBuffers::numClientBuffers() const {
602 return mImpl.numClientBuffers();
603}
604
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700605// static
606sp<Codec2Buffer> LinearInputBuffers::Alloc(
607 const std::shared_ptr<C2BlockPool> &pool, const sp<AMessage> &format) {
608 int32_t capacity = kLinearBufferSize;
609 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
610 if ((size_t)capacity > kMaxLinearBufferSize) {
611 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
612 capacity = kMaxLinearBufferSize;
613 }
614
Wonsik Kim666604a2020-05-14 16:57:49 -0700615 int64_t usageValue = 0;
616 (void)format->findInt64("android._C2MemoryUsage", &usageValue);
617 C2MemoryUsage usage{usageValue | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE};
Wonsik Kim469c8342019-04-11 16:46:09 -0700618 std::shared_ptr<C2LinearBlock> block;
619
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700620 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700621 if (err != C2_OK) {
622 return nullptr;
623 }
624
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700625 return LinearBlockBuffer::Allocate(format, block);
626}
627
628sp<Codec2Buffer> LinearInputBuffers::createNewBuffer() {
629 return Alloc(mPool, mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -0700630}
631
632// EncryptedLinearInputBuffers
633
634EncryptedLinearInputBuffers::EncryptedLinearInputBuffers(
635 bool secure,
636 const sp<MemoryDealer> &dealer,
637 const sp<ICrypto> &crypto,
638 int32_t heapSeqNum,
639 size_t capacity,
640 size_t numInputSlots,
641 const char *componentName, const char *name)
642 : LinearInputBuffers(componentName, name),
643 mUsage({0, 0}),
644 mDealer(dealer),
645 mCrypto(crypto),
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700646 mMemoryVector(new std::vector<Entry>){
Wonsik Kim469c8342019-04-11 16:46:09 -0700647 if (secure) {
648 mUsage = { C2MemoryUsage::READ_PROTECTED, 0 };
649 } else {
650 mUsage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
651 }
652 for (size_t i = 0; i < numInputSlots; ++i) {
653 sp<IMemory> memory = mDealer->allocate(capacity);
654 if (memory == nullptr) {
655 ALOGD("[%s] Failed to allocate memory from dealer: only %zu slots allocated",
656 mName, i);
657 break;
658 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700659 mMemoryVector->push_back({std::weak_ptr<C2LinearBlock>(), memory, heapSeqNum});
Wonsik Kim469c8342019-04-11 16:46:09 -0700660 }
661}
662
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700663std::unique_ptr<InputBuffers> EncryptedLinearInputBuffers::toArrayMode(size_t size) {
664 std::unique_ptr<InputBuffersArray> array(
665 new InputBuffersArray(mComponentName.c_str(), "1D-EncryptedInput[N]"));
666 array->setPool(mPool);
667 array->setFormat(mFormat);
668 array->initialize(
669 mImpl,
670 size,
671 [pool = mPool,
672 format = mFormat,
673 usage = mUsage,
674 memoryVector = mMemoryVector] () -> sp<Codec2Buffer> {
675 return Alloc(pool, format, usage, memoryVector);
676 });
677 return std::move(array);
678}
679
680
681// static
682sp<Codec2Buffer> EncryptedLinearInputBuffers::Alloc(
683 const std::shared_ptr<C2BlockPool> &pool,
684 const sp<AMessage> &format,
685 C2MemoryUsage usage,
686 const std::shared_ptr<std::vector<EncryptedLinearInputBuffers::Entry>> &memoryVector) {
687 int32_t capacity = kLinearBufferSize;
688 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
689 if ((size_t)capacity > kMaxLinearBufferSize) {
690 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
691 capacity = kMaxLinearBufferSize;
692 }
693
Wonsik Kim469c8342019-04-11 16:46:09 -0700694 sp<IMemory> memory;
695 size_t slot = 0;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700696 int32_t heapSeqNum = -1;
697 for (; slot < memoryVector->size(); ++slot) {
698 if (memoryVector->at(slot).block.expired()) {
699 memory = memoryVector->at(slot).memory;
700 heapSeqNum = memoryVector->at(slot).heapSeqNum;
Wonsik Kim469c8342019-04-11 16:46:09 -0700701 break;
702 }
703 }
704 if (memory == nullptr) {
705 return nullptr;
706 }
707
708 std::shared_ptr<C2LinearBlock> block;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700709 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700710 if (err != C2_OK || block == nullptr) {
711 return nullptr;
712 }
713
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700714 memoryVector->at(slot).block = block;
715 return new EncryptedLinearBlockBuffer(format, block, memory, heapSeqNum);
716}
717
718sp<Codec2Buffer> EncryptedLinearInputBuffers::createNewBuffer() {
719 // TODO: android_2020
720 return nullptr;
Wonsik Kim469c8342019-04-11 16:46:09 -0700721}
722
723// GraphicMetadataInputBuffers
724
725GraphicMetadataInputBuffers::GraphicMetadataInputBuffers(
726 const char *componentName, const char *name)
727 : InputBuffers(componentName, name),
728 mImpl(mName),
729 mStore(GetCodec2PlatformAllocatorStore()) { }
730
731bool GraphicMetadataInputBuffers::requestNewBuffer(
732 size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700733 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700734 if (newBuffer == nullptr) {
735 return false;
736 }
737 *index = mImpl.assignSlot(newBuffer);
738 *buffer = newBuffer;
739 return true;
740}
741
742bool GraphicMetadataInputBuffers::releaseBuffer(
743 const sp<MediaCodecBuffer> &buffer,
744 std::shared_ptr<C2Buffer> *c2buffer,
745 bool release) {
746 return mImpl.releaseSlot(buffer, c2buffer, release);
747}
748
749bool GraphicMetadataInputBuffers::expireComponentBuffer(
750 const std::shared_ptr<C2Buffer> &c2buffer) {
751 return mImpl.expireComponentBuffer(c2buffer);
752}
753
754void GraphicMetadataInputBuffers::flush() {
755 // This is no-op by default unless we're in array mode where we need to keep
756 // track of the flushed work.
757}
758
759std::unique_ptr<InputBuffers> GraphicMetadataInputBuffers::toArrayMode(
760 size_t size) {
761 std::shared_ptr<C2Allocator> alloc;
762 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
763 if (err != C2_OK) {
764 return nullptr;
765 }
766 std::unique_ptr<InputBuffersArray> array(
767 new InputBuffersArray(mComponentName.c_str(), "2D-MetaInput[N]"));
768 array->setPool(mPool);
769 array->setFormat(mFormat);
770 array->initialize(
771 mImpl,
772 size,
773 [format = mFormat, alloc]() -> sp<Codec2Buffer> {
774 return new GraphicMetadataBuffer(format, alloc);
775 });
776 return std::move(array);
777}
778
779size_t GraphicMetadataInputBuffers::numClientBuffers() const {
780 return mImpl.numClientBuffers();
781}
782
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700783sp<Codec2Buffer> GraphicMetadataInputBuffers::createNewBuffer() {
784 std::shared_ptr<C2Allocator> alloc;
785 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
786 if (err != C2_OK) {
787 return nullptr;
788 }
789 return new GraphicMetadataBuffer(mFormat, alloc);
790}
791
Wonsik Kim469c8342019-04-11 16:46:09 -0700792// GraphicInputBuffers
793
794GraphicInputBuffers::GraphicInputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -0700795 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -0700796 : InputBuffers(componentName, name),
797 mImpl(mName),
Wonsik Kim41d83432020-04-27 16:40:49 -0700798 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -0700799
800bool GraphicInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700801 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700802 if (newBuffer == nullptr) {
803 return false;
804 }
805 *index = mImpl.assignSlot(newBuffer);
806 handleImageData(newBuffer);
807 *buffer = newBuffer;
808 return true;
809}
810
811bool GraphicInputBuffers::releaseBuffer(
812 const sp<MediaCodecBuffer> &buffer,
813 std::shared_ptr<C2Buffer> *c2buffer,
814 bool release) {
815 return mImpl.releaseSlot(buffer, c2buffer, release);
816}
817
818bool GraphicInputBuffers::expireComponentBuffer(
819 const std::shared_ptr<C2Buffer> &c2buffer) {
820 return mImpl.expireComponentBuffer(c2buffer);
821}
822
823void GraphicInputBuffers::flush() {
824 // This is no-op by default unless we're in array mode where we need to keep
825 // track of the flushed work.
826}
827
828std::unique_ptr<InputBuffers> GraphicInputBuffers::toArrayMode(size_t size) {
829 std::unique_ptr<InputBuffersArray> array(
830 new InputBuffersArray(mComponentName.c_str(), "2D-BB-Input[N]"));
831 array->setPool(mPool);
832 array->setFormat(mFormat);
833 array->initialize(
834 mImpl,
835 size,
836 [pool = mPool, format = mFormat, lbp = mLocalBufferPool]() -> sp<Codec2Buffer> {
837 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
838 return AllocateGraphicBuffer(
839 pool, format, HAL_PIXEL_FORMAT_YV12, usage, lbp);
840 });
841 return std::move(array);
842}
843
844size_t GraphicInputBuffers::numClientBuffers() const {
845 return mImpl.numClientBuffers();
846}
847
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700848sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
Wonsik Kim666604a2020-05-14 16:57:49 -0700849 int64_t usageValue = 0;
850 (void)mFormat->findInt64("android._C2MemoryUsage", &usageValue);
851 C2MemoryUsage usage{usageValue | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE};
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700852 return AllocateGraphicBuffer(
853 mPool, mFormat, HAL_PIXEL_FORMAT_YV12, usage, mLocalBufferPool);
854}
855
Wonsik Kim469c8342019-04-11 16:46:09 -0700856// OutputBuffersArray
857
858void OutputBuffersArray::initialize(
859 const FlexBuffersImpl &impl,
860 size_t minSize,
861 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700862 mAlloc = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -0700863 mImpl.initialize(impl, minSize, allocate);
864}
865
866status_t OutputBuffersArray::registerBuffer(
867 const std::shared_ptr<C2Buffer> &buffer,
868 size_t *index,
869 sp<MediaCodecBuffer> *clientBuffer) {
870 sp<Codec2Buffer> c2Buffer;
871 status_t err = mImpl.grabBuffer(
872 index,
873 &c2Buffer,
874 [buffer](const sp<Codec2Buffer> &clientBuffer) {
875 return clientBuffer->canCopy(buffer);
876 });
877 if (err == WOULD_BLOCK) {
878 ALOGV("[%s] buffers temporarily not available", mName);
879 return err;
880 } else if (err != OK) {
881 ALOGD("[%s] grabBuffer failed: %d", mName, err);
882 return err;
883 }
884 c2Buffer->setFormat(mFormat);
885 if (!c2Buffer->copy(buffer)) {
886 ALOGD("[%s] copy buffer failed", mName);
887 return WOULD_BLOCK;
888 }
889 submit(c2Buffer);
890 handleImageData(c2Buffer);
891 *clientBuffer = c2Buffer;
892 ALOGV("[%s] grabbed buffer %zu", mName, *index);
893 return OK;
894}
895
896status_t OutputBuffersArray::registerCsd(
897 const C2StreamInitDataInfo::output *csd,
898 size_t *index,
899 sp<MediaCodecBuffer> *clientBuffer) {
900 sp<Codec2Buffer> c2Buffer;
901 status_t err = mImpl.grabBuffer(
902 index,
903 &c2Buffer,
904 [csd](const sp<Codec2Buffer> &clientBuffer) {
905 return clientBuffer->base() != nullptr
906 && clientBuffer->capacity() >= csd->flexCount();
907 });
908 if (err != OK) {
909 return err;
910 }
911 memcpy(c2Buffer->base(), csd->m.value, csd->flexCount());
912 c2Buffer->setRange(0, csd->flexCount());
913 c2Buffer->setFormat(mFormat);
914 *clientBuffer = c2Buffer;
915 return OK;
916}
917
918bool OutputBuffersArray::releaseBuffer(
919 const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) {
920 return mImpl.returnBuffer(buffer, c2buffer, true);
921}
922
923void OutputBuffersArray::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
924 (void)flushedWork;
925 mImpl.flush();
926 if (mSkipCutBuffer != nullptr) {
927 mSkipCutBuffer->clear();
928 }
929}
930
931void OutputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
932 mImpl.getArray(array);
933}
934
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700935size_t OutputBuffersArray::numClientBuffers() const {
936 return mImpl.numClientBuffers();
937}
938
Wonsik Kim469c8342019-04-11 16:46:09 -0700939void OutputBuffersArray::realloc(const std::shared_ptr<C2Buffer> &c2buffer) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700940 switch (c2buffer->data().type()) {
941 case C2BufferData::LINEAR: {
942 uint32_t size = kLinearBufferSize;
Nick Desaulniersd09eaea2019-10-07 20:19:39 -0700943 const std::vector<C2ConstLinearBlock> &linear_blocks = c2buffer->data().linearBlocks();
944 const uint32_t block_size = linear_blocks.front().size();
945 if (block_size < kMaxLinearBufferSize / 2) {
946 size = block_size * 2;
Wonsik Kim469c8342019-04-11 16:46:09 -0700947 } else {
948 size = kMaxLinearBufferSize;
949 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700950 mAlloc = [format = mFormat, size] {
Wonsik Kim469c8342019-04-11 16:46:09 -0700951 return new LocalLinearBuffer(format, new ABuffer(size));
952 };
Wonsik Kima39882b2019-06-20 16:13:56 -0700953 ALOGD("[%s] reallocating with linear buffer of size %u", mName, size);
Wonsik Kim469c8342019-04-11 16:46:09 -0700954 break;
955 }
956
Wonsik Kima39882b2019-06-20 16:13:56 -0700957 case C2BufferData::GRAPHIC: {
958 // This is only called for RawGraphicOutputBuffers.
959 mAlloc = [format = mFormat,
Wonsik Kim41d83432020-04-27 16:40:49 -0700960 lbp = LocalBufferPool::Create()] {
Wonsik Kima39882b2019-06-20 16:13:56 -0700961 return ConstGraphicBlockBuffer::AllocateEmpty(
962 format,
963 [lbp](size_t capacity) {
964 return lbp->newBuffer(capacity);
965 });
966 };
967 ALOGD("[%s] reallocating with graphic buffer: format = %s",
968 mName, mFormat->debugString().c_str());
969 break;
970 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700971
972 case C2BufferData::INVALID: [[fallthrough]];
973 case C2BufferData::LINEAR_CHUNKS: [[fallthrough]];
974 case C2BufferData::GRAPHIC_CHUNKS: [[fallthrough]];
975 default:
976 ALOGD("Unsupported type: %d", (int)c2buffer->data().type());
977 return;
978 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700979 mImpl.realloc(mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -0700980}
981
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700982void OutputBuffersArray::grow(size_t newSize) {
983 mImpl.grow(newSize, mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -0700984}
985
986// FlexOutputBuffers
987
988status_t FlexOutputBuffers::registerBuffer(
989 const std::shared_ptr<C2Buffer> &buffer,
990 size_t *index,
991 sp<MediaCodecBuffer> *clientBuffer) {
992 sp<Codec2Buffer> newBuffer = wrap(buffer);
993 if (newBuffer == nullptr) {
994 return NO_MEMORY;
995 }
996 newBuffer->setFormat(mFormat);
997 *index = mImpl.assignSlot(newBuffer);
998 handleImageData(newBuffer);
999 *clientBuffer = newBuffer;
1000 ALOGV("[%s] registered buffer %zu", mName, *index);
1001 return OK;
1002}
1003
1004status_t FlexOutputBuffers::registerCsd(
1005 const C2StreamInitDataInfo::output *csd,
1006 size_t *index,
1007 sp<MediaCodecBuffer> *clientBuffer) {
1008 sp<Codec2Buffer> newBuffer = new LocalLinearBuffer(
1009 mFormat, ABuffer::CreateAsCopy(csd->m.value, csd->flexCount()));
1010 *index = mImpl.assignSlot(newBuffer);
1011 *clientBuffer = newBuffer;
1012 return OK;
1013}
1014
1015bool FlexOutputBuffers::releaseBuffer(
1016 const sp<MediaCodecBuffer> &buffer,
1017 std::shared_ptr<C2Buffer> *c2buffer) {
1018 return mImpl.releaseSlot(buffer, c2buffer, true);
1019}
1020
1021void FlexOutputBuffers::flush(
1022 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1023 (void) flushedWork;
1024 // This is no-op by default unless we're in array mode where we need to keep
1025 // track of the flushed work.
1026}
1027
Wonsik Kima4e049d2020-04-28 19:42:23 +00001028std::unique_ptr<OutputBuffers> FlexOutputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001029 std::unique_ptr<OutputBuffersArray> array(new OutputBuffersArray(mComponentName.c_str()));
Wonsik Kima4e049d2020-04-28 19:42:23 +00001030 array->setFormat(mFormat);
1031 array->transferSkipCutBuffer(mSkipCutBuffer);
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001032 std::function<sp<Codec2Buffer>()> alloc = getAlloc();
1033 array->initialize(mImpl, size, alloc);
Wonsik Kima4e049d2020-04-28 19:42:23 +00001034 return std::move(array);
Wonsik Kim469c8342019-04-11 16:46:09 -07001035}
1036
1037size_t FlexOutputBuffers::numClientBuffers() const {
1038 return mImpl.numClientBuffers();
1039}
1040
1041// LinearOutputBuffers
1042
1043void LinearOutputBuffers::flush(
1044 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1045 if (mSkipCutBuffer != nullptr) {
1046 mSkipCutBuffer->clear();
1047 }
1048 FlexOutputBuffers::flush(flushedWork);
1049}
1050
1051sp<Codec2Buffer> LinearOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1052 if (buffer == nullptr) {
1053 ALOGV("[%s] using a dummy buffer", mName);
1054 return new LocalLinearBuffer(mFormat, new ABuffer(0));
1055 }
1056 if (buffer->data().type() != C2BufferData::LINEAR) {
1057 ALOGV("[%s] non-linear buffer %d", mName, buffer->data().type());
1058 // We expect linear output buffers from the component.
1059 return nullptr;
1060 }
1061 if (buffer->data().linearBlocks().size() != 1u) {
1062 ALOGV("[%s] no linear buffers", mName);
1063 // We expect one and only one linear block from the component.
1064 return nullptr;
1065 }
1066 sp<Codec2Buffer> clientBuffer = ConstLinearBlockBuffer::Allocate(mFormat, buffer);
1067 if (clientBuffer == nullptr) {
1068 ALOGD("[%s] ConstLinearBlockBuffer::Allocate failed", mName);
1069 return nullptr;
1070 }
1071 submit(clientBuffer);
1072 return clientBuffer;
1073}
1074
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001075std::function<sp<Codec2Buffer>()> LinearOutputBuffers::getAlloc() {
1076 return [format = mFormat]{
1077 // TODO: proper max output size
1078 return new LocalLinearBuffer(format, new ABuffer(kLinearBufferSize));
1079 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001080}
1081
1082// GraphicOutputBuffers
1083
1084sp<Codec2Buffer> GraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1085 return new DummyContainerBuffer(mFormat, buffer);
1086}
1087
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001088std::function<sp<Codec2Buffer>()> GraphicOutputBuffers::getAlloc() {
1089 return [format = mFormat]{
1090 return new DummyContainerBuffer(format);
1091 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001092}
1093
1094// RawGraphicOutputBuffers
1095
1096RawGraphicOutputBuffers::RawGraphicOutputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -07001097 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -07001098 : FlexOutputBuffers(componentName, name),
Wonsik Kim41d83432020-04-27 16:40:49 -07001099 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -07001100
1101sp<Codec2Buffer> RawGraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1102 if (buffer == nullptr) {
1103 sp<Codec2Buffer> c2buffer = ConstGraphicBlockBuffer::AllocateEmpty(
1104 mFormat,
1105 [lbp = mLocalBufferPool](size_t capacity) {
1106 return lbp->newBuffer(capacity);
1107 });
1108 if (c2buffer == nullptr) {
1109 ALOGD("[%s] ConstGraphicBlockBuffer::AllocateEmpty failed", mName);
1110 return nullptr;
1111 }
1112 c2buffer->setRange(0, 0);
1113 return c2buffer;
1114 } else {
1115 return ConstGraphicBlockBuffer::Allocate(
1116 mFormat,
1117 buffer,
1118 [lbp = mLocalBufferPool](size_t capacity) {
1119 return lbp->newBuffer(capacity);
1120 });
1121 }
1122}
1123
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001124std::function<sp<Codec2Buffer>()> RawGraphicOutputBuffers::getAlloc() {
1125 return [format = mFormat, lbp = mLocalBufferPool]{
1126 return ConstGraphicBlockBuffer::AllocateEmpty(
1127 format,
1128 [lbp](size_t capacity) {
1129 return lbp->newBuffer(capacity);
1130 });
1131 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001132}
1133
1134} // namespace android