blob: a9120c4bcd771f262e2b8e7539bfcd993972c527 [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
615 // TODO: read usage from intf
Wonsik Kim469c8342019-04-11 16:46:09 -0700616 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
617 std::shared_ptr<C2LinearBlock> block;
618
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700619 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700620 if (err != C2_OK) {
621 return nullptr;
622 }
623
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700624 return LinearBlockBuffer::Allocate(format, block);
625}
626
627sp<Codec2Buffer> LinearInputBuffers::createNewBuffer() {
628 return Alloc(mPool, mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -0700629}
630
631// EncryptedLinearInputBuffers
632
633EncryptedLinearInputBuffers::EncryptedLinearInputBuffers(
634 bool secure,
635 const sp<MemoryDealer> &dealer,
636 const sp<ICrypto> &crypto,
637 int32_t heapSeqNum,
638 size_t capacity,
639 size_t numInputSlots,
640 const char *componentName, const char *name)
641 : LinearInputBuffers(componentName, name),
642 mUsage({0, 0}),
643 mDealer(dealer),
644 mCrypto(crypto),
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700645 mMemoryVector(new std::vector<Entry>){
Wonsik Kim469c8342019-04-11 16:46:09 -0700646 if (secure) {
647 mUsage = { C2MemoryUsage::READ_PROTECTED, 0 };
648 } else {
649 mUsage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
650 }
651 for (size_t i = 0; i < numInputSlots; ++i) {
652 sp<IMemory> memory = mDealer->allocate(capacity);
653 if (memory == nullptr) {
654 ALOGD("[%s] Failed to allocate memory from dealer: only %zu slots allocated",
655 mName, i);
656 break;
657 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700658 mMemoryVector->push_back({std::weak_ptr<C2LinearBlock>(), memory, heapSeqNum});
Wonsik Kim469c8342019-04-11 16:46:09 -0700659 }
660}
661
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700662std::unique_ptr<InputBuffers> EncryptedLinearInputBuffers::toArrayMode(size_t size) {
663 std::unique_ptr<InputBuffersArray> array(
664 new InputBuffersArray(mComponentName.c_str(), "1D-EncryptedInput[N]"));
665 array->setPool(mPool);
666 array->setFormat(mFormat);
667 array->initialize(
668 mImpl,
669 size,
670 [pool = mPool,
671 format = mFormat,
672 usage = mUsage,
673 memoryVector = mMemoryVector] () -> sp<Codec2Buffer> {
674 return Alloc(pool, format, usage, memoryVector);
675 });
676 return std::move(array);
677}
678
679
680// static
681sp<Codec2Buffer> EncryptedLinearInputBuffers::Alloc(
682 const std::shared_ptr<C2BlockPool> &pool,
683 const sp<AMessage> &format,
684 C2MemoryUsage usage,
685 const std::shared_ptr<std::vector<EncryptedLinearInputBuffers::Entry>> &memoryVector) {
686 int32_t capacity = kLinearBufferSize;
687 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
688 if ((size_t)capacity > kMaxLinearBufferSize) {
689 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
690 capacity = kMaxLinearBufferSize;
691 }
692
Wonsik Kim469c8342019-04-11 16:46:09 -0700693 sp<IMemory> memory;
694 size_t slot = 0;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700695 int32_t heapSeqNum = -1;
696 for (; slot < memoryVector->size(); ++slot) {
697 if (memoryVector->at(slot).block.expired()) {
698 memory = memoryVector->at(slot).memory;
699 heapSeqNum = memoryVector->at(slot).heapSeqNum;
Wonsik Kim469c8342019-04-11 16:46:09 -0700700 break;
701 }
702 }
703 if (memory == nullptr) {
704 return nullptr;
705 }
706
707 std::shared_ptr<C2LinearBlock> block;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700708 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700709 if (err != C2_OK || block == nullptr) {
710 return nullptr;
711 }
712
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700713 memoryVector->at(slot).block = block;
714 return new EncryptedLinearBlockBuffer(format, block, memory, heapSeqNum);
715}
716
717sp<Codec2Buffer> EncryptedLinearInputBuffers::createNewBuffer() {
718 // TODO: android_2020
719 return nullptr;
Wonsik Kim469c8342019-04-11 16:46:09 -0700720}
721
722// GraphicMetadataInputBuffers
723
724GraphicMetadataInputBuffers::GraphicMetadataInputBuffers(
725 const char *componentName, const char *name)
726 : InputBuffers(componentName, name),
727 mImpl(mName),
728 mStore(GetCodec2PlatformAllocatorStore()) { }
729
730bool GraphicMetadataInputBuffers::requestNewBuffer(
731 size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700732 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700733 if (newBuffer == nullptr) {
734 return false;
735 }
736 *index = mImpl.assignSlot(newBuffer);
737 *buffer = newBuffer;
738 return true;
739}
740
741bool GraphicMetadataInputBuffers::releaseBuffer(
742 const sp<MediaCodecBuffer> &buffer,
743 std::shared_ptr<C2Buffer> *c2buffer,
744 bool release) {
745 return mImpl.releaseSlot(buffer, c2buffer, release);
746}
747
748bool GraphicMetadataInputBuffers::expireComponentBuffer(
749 const std::shared_ptr<C2Buffer> &c2buffer) {
750 return mImpl.expireComponentBuffer(c2buffer);
751}
752
753void GraphicMetadataInputBuffers::flush() {
754 // This is no-op by default unless we're in array mode where we need to keep
755 // track of the flushed work.
756}
757
758std::unique_ptr<InputBuffers> GraphicMetadataInputBuffers::toArrayMode(
759 size_t size) {
760 std::shared_ptr<C2Allocator> alloc;
761 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
762 if (err != C2_OK) {
763 return nullptr;
764 }
765 std::unique_ptr<InputBuffersArray> array(
766 new InputBuffersArray(mComponentName.c_str(), "2D-MetaInput[N]"));
767 array->setPool(mPool);
768 array->setFormat(mFormat);
769 array->initialize(
770 mImpl,
771 size,
772 [format = mFormat, alloc]() -> sp<Codec2Buffer> {
773 return new GraphicMetadataBuffer(format, alloc);
774 });
775 return std::move(array);
776}
777
778size_t GraphicMetadataInputBuffers::numClientBuffers() const {
779 return mImpl.numClientBuffers();
780}
781
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700782sp<Codec2Buffer> GraphicMetadataInputBuffers::createNewBuffer() {
783 std::shared_ptr<C2Allocator> alloc;
784 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
785 if (err != C2_OK) {
786 return nullptr;
787 }
788 return new GraphicMetadataBuffer(mFormat, alloc);
789}
790
Wonsik Kim469c8342019-04-11 16:46:09 -0700791// GraphicInputBuffers
792
793GraphicInputBuffers::GraphicInputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -0700794 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -0700795 : InputBuffers(componentName, name),
796 mImpl(mName),
Wonsik Kim41d83432020-04-27 16:40:49 -0700797 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -0700798
799bool GraphicInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700800 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700801 if (newBuffer == nullptr) {
802 return false;
803 }
804 *index = mImpl.assignSlot(newBuffer);
805 handleImageData(newBuffer);
806 *buffer = newBuffer;
807 return true;
808}
809
810bool GraphicInputBuffers::releaseBuffer(
811 const sp<MediaCodecBuffer> &buffer,
812 std::shared_ptr<C2Buffer> *c2buffer,
813 bool release) {
814 return mImpl.releaseSlot(buffer, c2buffer, release);
815}
816
817bool GraphicInputBuffers::expireComponentBuffer(
818 const std::shared_ptr<C2Buffer> &c2buffer) {
819 return mImpl.expireComponentBuffer(c2buffer);
820}
821
822void GraphicInputBuffers::flush() {
823 // This is no-op by default unless we're in array mode where we need to keep
824 // track of the flushed work.
825}
826
827std::unique_ptr<InputBuffers> GraphicInputBuffers::toArrayMode(size_t size) {
828 std::unique_ptr<InputBuffersArray> array(
829 new InputBuffersArray(mComponentName.c_str(), "2D-BB-Input[N]"));
830 array->setPool(mPool);
831 array->setFormat(mFormat);
832 array->initialize(
833 mImpl,
834 size,
835 [pool = mPool, format = mFormat, lbp = mLocalBufferPool]() -> sp<Codec2Buffer> {
836 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
837 return AllocateGraphicBuffer(
838 pool, format, HAL_PIXEL_FORMAT_YV12, usage, lbp);
839 });
840 return std::move(array);
841}
842
843size_t GraphicInputBuffers::numClientBuffers() const {
844 return mImpl.numClientBuffers();
845}
846
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700847sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
848 // TODO: read usage from intf
849 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
850 return AllocateGraphicBuffer(
851 mPool, mFormat, HAL_PIXEL_FORMAT_YV12, usage, mLocalBufferPool);
852}
853
Wonsik Kim469c8342019-04-11 16:46:09 -0700854// OutputBuffersArray
855
856void OutputBuffersArray::initialize(
857 const FlexBuffersImpl &impl,
858 size_t minSize,
859 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700860 mAlloc = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -0700861 mImpl.initialize(impl, minSize, allocate);
862}
863
864status_t OutputBuffersArray::registerBuffer(
865 const std::shared_ptr<C2Buffer> &buffer,
866 size_t *index,
867 sp<MediaCodecBuffer> *clientBuffer) {
868 sp<Codec2Buffer> c2Buffer;
869 status_t err = mImpl.grabBuffer(
870 index,
871 &c2Buffer,
872 [buffer](const sp<Codec2Buffer> &clientBuffer) {
873 return clientBuffer->canCopy(buffer);
874 });
875 if (err == WOULD_BLOCK) {
876 ALOGV("[%s] buffers temporarily not available", mName);
877 return err;
878 } else if (err != OK) {
879 ALOGD("[%s] grabBuffer failed: %d", mName, err);
880 return err;
881 }
882 c2Buffer->setFormat(mFormat);
883 if (!c2Buffer->copy(buffer)) {
884 ALOGD("[%s] copy buffer failed", mName);
885 return WOULD_BLOCK;
886 }
887 submit(c2Buffer);
888 handleImageData(c2Buffer);
889 *clientBuffer = c2Buffer;
890 ALOGV("[%s] grabbed buffer %zu", mName, *index);
891 return OK;
892}
893
894status_t OutputBuffersArray::registerCsd(
895 const C2StreamInitDataInfo::output *csd,
896 size_t *index,
897 sp<MediaCodecBuffer> *clientBuffer) {
898 sp<Codec2Buffer> c2Buffer;
899 status_t err = mImpl.grabBuffer(
900 index,
901 &c2Buffer,
902 [csd](const sp<Codec2Buffer> &clientBuffer) {
903 return clientBuffer->base() != nullptr
904 && clientBuffer->capacity() >= csd->flexCount();
905 });
906 if (err != OK) {
907 return err;
908 }
909 memcpy(c2Buffer->base(), csd->m.value, csd->flexCount());
910 c2Buffer->setRange(0, csd->flexCount());
911 c2Buffer->setFormat(mFormat);
912 *clientBuffer = c2Buffer;
913 return OK;
914}
915
916bool OutputBuffersArray::releaseBuffer(
917 const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) {
918 return mImpl.returnBuffer(buffer, c2buffer, true);
919}
920
921void OutputBuffersArray::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
922 (void)flushedWork;
923 mImpl.flush();
924 if (mSkipCutBuffer != nullptr) {
925 mSkipCutBuffer->clear();
926 }
927}
928
929void OutputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
930 mImpl.getArray(array);
931}
932
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700933size_t OutputBuffersArray::numClientBuffers() const {
934 return mImpl.numClientBuffers();
935}
936
Wonsik Kim469c8342019-04-11 16:46:09 -0700937void OutputBuffersArray::realloc(const std::shared_ptr<C2Buffer> &c2buffer) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700938 switch (c2buffer->data().type()) {
939 case C2BufferData::LINEAR: {
940 uint32_t size = kLinearBufferSize;
Nick Desaulniersd09eaea2019-10-07 20:19:39 -0700941 const std::vector<C2ConstLinearBlock> &linear_blocks = c2buffer->data().linearBlocks();
942 const uint32_t block_size = linear_blocks.front().size();
943 if (block_size < kMaxLinearBufferSize / 2) {
944 size = block_size * 2;
Wonsik Kim469c8342019-04-11 16:46:09 -0700945 } else {
946 size = kMaxLinearBufferSize;
947 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700948 mAlloc = [format = mFormat, size] {
Wonsik Kim469c8342019-04-11 16:46:09 -0700949 return new LocalLinearBuffer(format, new ABuffer(size));
950 };
Wonsik Kima39882b2019-06-20 16:13:56 -0700951 ALOGD("[%s] reallocating with linear buffer of size %u", mName, size);
Wonsik Kim469c8342019-04-11 16:46:09 -0700952 break;
953 }
954
Wonsik Kima39882b2019-06-20 16:13:56 -0700955 case C2BufferData::GRAPHIC: {
956 // This is only called for RawGraphicOutputBuffers.
957 mAlloc = [format = mFormat,
Wonsik Kim41d83432020-04-27 16:40:49 -0700958 lbp = LocalBufferPool::Create()] {
Wonsik Kima39882b2019-06-20 16:13:56 -0700959 return ConstGraphicBlockBuffer::AllocateEmpty(
960 format,
961 [lbp](size_t capacity) {
962 return lbp->newBuffer(capacity);
963 });
964 };
965 ALOGD("[%s] reallocating with graphic buffer: format = %s",
966 mName, mFormat->debugString().c_str());
967 break;
968 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700969
970 case C2BufferData::INVALID: [[fallthrough]];
971 case C2BufferData::LINEAR_CHUNKS: [[fallthrough]];
972 case C2BufferData::GRAPHIC_CHUNKS: [[fallthrough]];
973 default:
974 ALOGD("Unsupported type: %d", (int)c2buffer->data().type());
975 return;
976 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700977 mImpl.realloc(mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -0700978}
979
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700980void OutputBuffersArray::grow(size_t newSize) {
981 mImpl.grow(newSize, mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -0700982}
983
984// FlexOutputBuffers
985
986status_t FlexOutputBuffers::registerBuffer(
987 const std::shared_ptr<C2Buffer> &buffer,
988 size_t *index,
989 sp<MediaCodecBuffer> *clientBuffer) {
990 sp<Codec2Buffer> newBuffer = wrap(buffer);
991 if (newBuffer == nullptr) {
992 return NO_MEMORY;
993 }
994 newBuffer->setFormat(mFormat);
995 *index = mImpl.assignSlot(newBuffer);
996 handleImageData(newBuffer);
997 *clientBuffer = newBuffer;
998 ALOGV("[%s] registered buffer %zu", mName, *index);
999 return OK;
1000}
1001
1002status_t FlexOutputBuffers::registerCsd(
1003 const C2StreamInitDataInfo::output *csd,
1004 size_t *index,
1005 sp<MediaCodecBuffer> *clientBuffer) {
1006 sp<Codec2Buffer> newBuffer = new LocalLinearBuffer(
1007 mFormat, ABuffer::CreateAsCopy(csd->m.value, csd->flexCount()));
1008 *index = mImpl.assignSlot(newBuffer);
1009 *clientBuffer = newBuffer;
1010 return OK;
1011}
1012
1013bool FlexOutputBuffers::releaseBuffer(
1014 const sp<MediaCodecBuffer> &buffer,
1015 std::shared_ptr<C2Buffer> *c2buffer) {
1016 return mImpl.releaseSlot(buffer, c2buffer, true);
1017}
1018
1019void FlexOutputBuffers::flush(
1020 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1021 (void) flushedWork;
1022 // This is no-op by default unless we're in array mode where we need to keep
1023 // track of the flushed work.
1024}
1025
Wonsik Kima4e049d2020-04-28 19:42:23 +00001026std::unique_ptr<OutputBuffers> FlexOutputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001027 std::unique_ptr<OutputBuffersArray> array(new OutputBuffersArray(mComponentName.c_str()));
Wonsik Kima4e049d2020-04-28 19:42:23 +00001028 array->setFormat(mFormat);
1029 array->transferSkipCutBuffer(mSkipCutBuffer);
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001030 std::function<sp<Codec2Buffer>()> alloc = getAlloc();
1031 array->initialize(mImpl, size, alloc);
Wonsik Kima4e049d2020-04-28 19:42:23 +00001032 return std::move(array);
Wonsik Kim469c8342019-04-11 16:46:09 -07001033}
1034
1035size_t FlexOutputBuffers::numClientBuffers() const {
1036 return mImpl.numClientBuffers();
1037}
1038
1039// LinearOutputBuffers
1040
1041void LinearOutputBuffers::flush(
1042 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1043 if (mSkipCutBuffer != nullptr) {
1044 mSkipCutBuffer->clear();
1045 }
1046 FlexOutputBuffers::flush(flushedWork);
1047}
1048
1049sp<Codec2Buffer> LinearOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1050 if (buffer == nullptr) {
1051 ALOGV("[%s] using a dummy buffer", mName);
1052 return new LocalLinearBuffer(mFormat, new ABuffer(0));
1053 }
1054 if (buffer->data().type() != C2BufferData::LINEAR) {
1055 ALOGV("[%s] non-linear buffer %d", mName, buffer->data().type());
1056 // We expect linear output buffers from the component.
1057 return nullptr;
1058 }
1059 if (buffer->data().linearBlocks().size() != 1u) {
1060 ALOGV("[%s] no linear buffers", mName);
1061 // We expect one and only one linear block from the component.
1062 return nullptr;
1063 }
1064 sp<Codec2Buffer> clientBuffer = ConstLinearBlockBuffer::Allocate(mFormat, buffer);
1065 if (clientBuffer == nullptr) {
1066 ALOGD("[%s] ConstLinearBlockBuffer::Allocate failed", mName);
1067 return nullptr;
1068 }
1069 submit(clientBuffer);
1070 return clientBuffer;
1071}
1072
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001073std::function<sp<Codec2Buffer>()> LinearOutputBuffers::getAlloc() {
1074 return [format = mFormat]{
1075 // TODO: proper max output size
1076 return new LocalLinearBuffer(format, new ABuffer(kLinearBufferSize));
1077 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001078}
1079
1080// GraphicOutputBuffers
1081
1082sp<Codec2Buffer> GraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1083 return new DummyContainerBuffer(mFormat, buffer);
1084}
1085
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001086std::function<sp<Codec2Buffer>()> GraphicOutputBuffers::getAlloc() {
1087 return [format = mFormat]{
1088 return new DummyContainerBuffer(format);
1089 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001090}
1091
1092// RawGraphicOutputBuffers
1093
1094RawGraphicOutputBuffers::RawGraphicOutputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -07001095 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -07001096 : FlexOutputBuffers(componentName, name),
Wonsik Kim41d83432020-04-27 16:40:49 -07001097 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -07001098
1099sp<Codec2Buffer> RawGraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1100 if (buffer == nullptr) {
1101 sp<Codec2Buffer> c2buffer = ConstGraphicBlockBuffer::AllocateEmpty(
1102 mFormat,
1103 [lbp = mLocalBufferPool](size_t capacity) {
1104 return lbp->newBuffer(capacity);
1105 });
1106 if (c2buffer == nullptr) {
1107 ALOGD("[%s] ConstGraphicBlockBuffer::AllocateEmpty failed", mName);
1108 return nullptr;
1109 }
1110 c2buffer->setRange(0, 0);
1111 return c2buffer;
1112 } else {
1113 return ConstGraphicBlockBuffer::Allocate(
1114 mFormat,
1115 buffer,
1116 [lbp = mLocalBufferPool](size_t capacity) {
1117 return lbp->newBuffer(capacity);
1118 });
1119 }
1120}
1121
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001122std::function<sp<Codec2Buffer>()> RawGraphicOutputBuffers::getAlloc() {
1123 return [format = mFormat, lbp = mLocalBufferPool]{
1124 return ConstGraphicBlockBuffer::AllocateEmpty(
1125 format,
1126 [lbp](size_t capacity) {
1127 return lbp->newBuffer(capacity);
1128 });
1129 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001130}
1131
1132} // namespace android