blob: 57c70c1fcc1f5b1f4c14bb0776102a341458d037 [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>
Wonsik Kim6f23cfc2021-09-24 05:45:52 -070024#include <media/stagefright/foundation/MediaDefs.h>
Wonsik Kim469c8342019-04-11 16:46:09 -070025#include <media/stagefright/MediaCodecConstants.h>
Wonsik Kim155d5cb2019-10-09 12:49:49 -070026#include <media/stagefright/SkipCutBuffer.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070027#include <mediadrm/ICrypto.h>
Wonsik Kim469c8342019-04-11 16:46:09 -070028
29#include "CCodecBuffers.h"
Wonsik Kimd79ee1f2020-08-27 17:41:56 -070030#include "Codec2Mapper.h"
Wonsik Kim469c8342019-04-11 16:46:09 -070031
32namespace android {
33
34namespace {
35
My Nameac29e592022-03-28 13:53:32 -070036constexpr uint32_t PIXEL_FORMAT_UNKNOWN = 0;
37
David Stevens94b608f2021-07-29 15:04:14 +090038sp<GraphicBlockBuffer> AllocateInputGraphicBuffer(
Wonsik Kim469c8342019-04-11 16:46:09 -070039 const std::shared_ptr<C2BlockPool> &pool,
40 const sp<AMessage> &format,
41 uint32_t pixelFormat,
42 const C2MemoryUsage &usage,
43 const std::shared_ptr<LocalBufferPool> &localBufferPool) {
44 int32_t width, height;
45 if (!format->findInt32("width", &width) || !format->findInt32("height", &height)) {
46 ALOGD("format lacks width or height");
47 return nullptr;
48 }
49
David Stevens94b608f2021-07-29 15:04:14 +090050 int64_t usageValue = 0;
51 (void)format->findInt64("android._C2MemoryUsage", &usageValue);
52 C2MemoryUsage fullUsage{usageValue | usage.expected};
53
Wonsik Kim469c8342019-04-11 16:46:09 -070054 std::shared_ptr<C2GraphicBlock> block;
55 c2_status_t err = pool->fetchGraphicBlock(
David Stevens94b608f2021-07-29 15:04:14 +090056 width, height, pixelFormat, fullUsage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -070057 if (err != C2_OK) {
58 ALOGD("fetch graphic block failed: %d", err);
59 return nullptr;
60 }
61
62 return GraphicBlockBuffer::Allocate(
63 format,
64 block,
65 [localBufferPool](size_t capacity) {
66 return localBufferPool->newBuffer(capacity);
67 });
68}
69
70} // namespace
71
72// CCodecBuffers
73
74void CCodecBuffers::setFormat(const sp<AMessage> &format) {
75 CHECK(format != nullptr);
76 mFormat = format;
77}
78
79sp<AMessage> CCodecBuffers::dupFormat() {
80 return mFormat != nullptr ? mFormat->dup() : nullptr;
81}
82
83void CCodecBuffers::handleImageData(const sp<Codec2Buffer> &buffer) {
84 sp<ABuffer> imageDataCandidate = buffer->getImageData();
85 if (imageDataCandidate == nullptr) {
Wonsik Kim4a3c0462021-03-09 15:45:05 -080086 if (mFormatWithImageData) {
87 // We previously sent the format with image data, so use the same format.
88 buffer->setFormat(mFormatWithImageData);
89 }
Wonsik Kim469c8342019-04-11 16:46:09 -070090 return;
91 }
Wonsik Kim4a3c0462021-03-09 15:45:05 -080092 if (!mLastImageData
93 || imageDataCandidate->size() != mLastImageData->size()
94 || memcmp(imageDataCandidate->data(),
95 mLastImageData->data(),
96 mLastImageData->size()) != 0) {
Wonsik Kim469c8342019-04-11 16:46:09 -070097 ALOGD("[%s] updating image-data", mName);
Wonsik Kim4a3c0462021-03-09 15:45:05 -080098 mFormatWithImageData = dupFormat();
99 mLastImageData = imageDataCandidate;
100 mFormatWithImageData->setBuffer("image-data", imageDataCandidate);
Wonsik Kim469c8342019-04-11 16:46:09 -0700101 MediaImage2 *img = (MediaImage2*)imageDataCandidate->data();
102 if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
103 int32_t stride = img->mPlane[0].mRowInc;
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800104 mFormatWithImageData->setInt32(KEY_STRIDE, stride);
Vinay Kaliaef5fc712021-09-15 23:59:50 +0000105 mFormatWithImageData->setInt32(KEY_WIDTH, img->mWidth);
106 mFormatWithImageData->setInt32(KEY_HEIGHT, img->mHeight);
107 ALOGD("[%s] updating stride = %d, width: %d, height: %d",
108 mName, stride, img->mWidth, img->mHeight);
Wonsik Kim469c8342019-04-11 16:46:09 -0700109 if (img->mNumPlanes > 1 && stride > 0) {
Taehwan Kimfd9b8092020-09-17 12:26:40 +0900110 int64_t offsetDelta =
111 (int64_t)img->mPlane[1].mOffset - (int64_t)img->mPlane[0].mOffset;
112 int32_t vstride = int32_t(offsetDelta / stride);
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800113 mFormatWithImageData->setInt32(KEY_SLICE_HEIGHT, vstride);
Wonsik Kim469c8342019-04-11 16:46:09 -0700114 ALOGD("[%s] updating vstride = %d", mName, vstride);
Wonsik Kim2eb06312020-12-03 11:07:58 -0800115 buffer->setRange(
116 img->mPlane[0].mOffset,
117 buffer->size() - img->mPlane[0].mOffset);
Wonsik Kim469c8342019-04-11 16:46:09 -0700118 }
119 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700120 }
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800121 buffer->setFormat(mFormatWithImageData);
Wonsik Kim469c8342019-04-11 16:46:09 -0700122}
123
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700124// InputBuffers
125
126sp<Codec2Buffer> InputBuffers::cloneAndReleaseBuffer(const sp<MediaCodecBuffer> &buffer) {
127 sp<Codec2Buffer> copy = createNewBuffer();
128 if (copy == nullptr) {
129 return nullptr;
130 }
131 std::shared_ptr<C2Buffer> c2buffer;
132 if (!releaseBuffer(buffer, &c2buffer, true)) {
133 return nullptr;
134 }
135 if (!copy->canCopy(c2buffer)) {
136 return nullptr;
137 }
138 if (!copy->copy(c2buffer)) {
139 return nullptr;
140 }
Wonsik Kimfb5ca492021-08-11 14:18:19 -0700141 copy->meta()->extend(buffer->meta());
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700142 return copy;
143}
144
Wonsik Kim469c8342019-04-11 16:46:09 -0700145// OutputBuffers
146
Wonsik Kim41d83432020-04-27 16:40:49 -0700147OutputBuffers::OutputBuffers(const char *componentName, const char *name)
148 : CCodecBuffers(componentName, name) { }
149
150OutputBuffers::~OutputBuffers() = default;
151
Wonsik Kim469c8342019-04-11 16:46:09 -0700152void OutputBuffers::initSkipCutBuffer(
153 int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount) {
154 CHECK(mSkipCutBuffer == nullptr);
155 mDelay = delay;
156 mPadding = padding;
157 mSampleRate = sampleRate;
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700158 mChannelCount = channelCount;
159 setSkipCutBuffer(delay, padding);
Wonsik Kim469c8342019-04-11 16:46:09 -0700160}
161
162void OutputBuffers::updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount) {
163 if (mSkipCutBuffer == nullptr) {
164 return;
165 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700166 if (mSampleRate == sampleRate && mChannelCount == channelCount) {
167 return;
168 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700169 int32_t delay = mDelay;
170 int32_t padding = mPadding;
171 if (sampleRate != mSampleRate) {
172 delay = ((int64_t)delay * sampleRate) / mSampleRate;
173 padding = ((int64_t)padding * sampleRate) / mSampleRate;
174 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700175 mSampleRate = sampleRate;
176 mChannelCount = channelCount;
177 setSkipCutBuffer(delay, padding);
Wonsik Kim469c8342019-04-11 16:46:09 -0700178}
179
Wonsik Kim3b4349a2020-11-10 11:54:15 -0800180void OutputBuffers::updateSkipCutBuffer(const sp<AMessage> &format) {
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700181 AString mediaType;
182 if (format->findString(KEY_MIME, &mediaType)
183 && mediaType == MIMETYPE_AUDIO_RAW) {
184 int32_t channelCount;
185 int32_t sampleRate;
186 if (format->findInt32(KEY_CHANNEL_COUNT, &channelCount)
187 && format->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
188 updateSkipCutBuffer(sampleRate, channelCount);
189 }
190 }
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700191}
192
Wonsik Kim469c8342019-04-11 16:46:09 -0700193void OutputBuffers::submit(const sp<MediaCodecBuffer> &buffer) {
194 if (mSkipCutBuffer != nullptr) {
195 mSkipCutBuffer->submit(buffer);
196 }
197}
198
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700199void OutputBuffers::setSkipCutBuffer(int32_t skip, int32_t cut) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700200 if (mSkipCutBuffer != nullptr) {
201 size_t prevSize = mSkipCutBuffer->size();
202 if (prevSize != 0u) {
203 ALOGD("[%s] Replacing SkipCutBuffer holding %zu bytes", mName, prevSize);
204 }
205 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700206 mSkipCutBuffer = new SkipCutBuffer(skip, cut, mChannelCount);
Wonsik Kim469c8342019-04-11 16:46:09 -0700207}
208
Wonsik Kim6f23cfc2021-09-24 05:45:52 -0700209bool OutputBuffers::convert(
210 const std::shared_ptr<C2Buffer> &src, sp<Codec2Buffer> *dst) {
211 if (!src || src->data().type() != C2BufferData::LINEAR) {
212 return false;
213 }
214 int32_t configEncoding = kAudioEncodingPcm16bit;
215 int32_t codecEncoding = kAudioEncodingPcm16bit;
216 if (mFormat->findInt32("android._codec-pcm-encoding", &codecEncoding)
217 && mFormat->findInt32("android._config-pcm-encoding", &configEncoding)) {
218 if (mSrcEncoding != codecEncoding || mDstEncoding != configEncoding) {
219 if (codecEncoding != configEncoding) {
220 mDataConverter = AudioConverter::Create(
221 (AudioEncoding)codecEncoding, (AudioEncoding)configEncoding);
222 ALOGD_IF(mDataConverter, "[%s] Converter created from %d to %d",
223 mName, codecEncoding, configEncoding);
224 mFormatWithConverter = mFormat->dup();
225 mFormatWithConverter->setInt32(KEY_PCM_ENCODING, configEncoding);
226 } else {
227 mDataConverter = nullptr;
228 mFormatWithConverter = nullptr;
229 }
230 mSrcEncoding = codecEncoding;
231 mDstEncoding = configEncoding;
232 }
233 if (int encoding; !mFormat->findInt32(KEY_PCM_ENCODING, &encoding)
234 || encoding != mDstEncoding) {
235 }
236 }
237 if (!mDataConverter) {
238 return false;
239 }
240 sp<MediaCodecBuffer> srcBuffer = ConstLinearBlockBuffer::Allocate(mFormat, src);
241 if (!srcBuffer) {
242 return false;
243 }
Greg Kaiser92dc4542021-10-08 06:58:19 -0700244 if (!*dst) {
Wonsik Kim6f23cfc2021-09-24 05:45:52 -0700245 *dst = new Codec2Buffer(
246 mFormat,
247 new ABuffer(mDataConverter->targetSize(srcBuffer->size())));
248 }
249 sp<MediaCodecBuffer> dstBuffer = *dst;
250 status_t err = mDataConverter->convert(srcBuffer, dstBuffer);
251 if (err != OK) {
252 ALOGD("[%s] buffer conversion failed: %d", mName, err);
253 return false;
254 }
255 dstBuffer->setFormat(mFormatWithConverter);
256 return true;
257}
258
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700259void OutputBuffers::clearStash() {
260 mPending.clear();
261 mReorderStash.clear();
262 mDepth = 0;
263 mKey = C2Config::ORDINAL;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700264}
265
266void OutputBuffers::flushStash() {
267 for (StashEntry& e : mPending) {
268 e.notify = false;
269 }
270 for (StashEntry& e : mReorderStash) {
271 e.notify = false;
272 }
273}
274
275uint32_t OutputBuffers::getReorderDepth() const {
276 return mDepth;
277}
278
279void OutputBuffers::setReorderDepth(uint32_t depth) {
280 mPending.splice(mPending.end(), mReorderStash);
281 mDepth = depth;
282}
283
284void OutputBuffers::setReorderKey(C2Config::ordinal_key_t key) {
285 mPending.splice(mPending.end(), mReorderStash);
286 mKey = key;
287}
288
289void OutputBuffers::pushToStash(
290 const std::shared_ptr<C2Buffer>& buffer,
291 bool notify,
292 int64_t timestamp,
293 int32_t flags,
294 const sp<AMessage>& format,
295 const C2WorkOrdinalStruct& ordinal) {
My Nameac29e592022-03-28 13:53:32 -0700296 bool eos = flags & BUFFER_FLAG_END_OF_STREAM;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700297 if (!buffer && eos) {
298 // TRICKY: we may be violating ordering of the stash here. Because we
299 // don't expect any more emplace() calls after this, the ordering should
300 // not matter.
301 mReorderStash.emplace_back(
302 buffer, notify, timestamp, flags, format, ordinal);
303 } else {
My Nameac29e592022-03-28 13:53:32 -0700304 flags = flags & ~BUFFER_FLAG_END_OF_STREAM;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700305 auto it = mReorderStash.begin();
306 for (; it != mReorderStash.end(); ++it) {
307 if (less(ordinal, it->ordinal)) {
308 break;
309 }
310 }
311 mReorderStash.emplace(it,
312 buffer, notify, timestamp, flags, format, ordinal);
313 if (eos) {
314 mReorderStash.back().flags =
My Nameac29e592022-03-28 13:53:32 -0700315 mReorderStash.back().flags | BUFFER_FLAG_END_OF_STREAM;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700316 }
317 }
318 while (!mReorderStash.empty() && mReorderStash.size() > mDepth) {
319 mPending.push_back(mReorderStash.front());
320 mReorderStash.pop_front();
321 }
322 ALOGV("[%s] %s: pushToStash -- pending size = %zu", mName, __func__, mPending.size());
323}
324
325OutputBuffers::BufferAction OutputBuffers::popFromStashAndRegister(
326 std::shared_ptr<C2Buffer>* c2Buffer,
327 size_t* index,
328 sp<MediaCodecBuffer>* outBuffer) {
329 if (mPending.empty()) {
330 return SKIP;
331 }
332
333 // Retrieve the first entry.
334 StashEntry &entry = mPending.front();
335
336 *c2Buffer = entry.buffer;
337 sp<AMessage> outputFormat = entry.format;
338
Wonsik Kim3b4349a2020-11-10 11:54:15 -0800339 if (entry.notify && mFormat != outputFormat) {
340 updateSkipCutBuffer(outputFormat);
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800341 // Trigger image data processing to the new format
342 mLastImageData.clear();
Wonsik Kim3b4349a2020-11-10 11:54:15 -0800343 ALOGV("[%s] popFromStashAndRegister: output format reference changed: %p -> %p",
344 mName, mFormat.get(), outputFormat.get());
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800345 ALOGD("[%s] popFromStashAndRegister: at %lldus, output format changed to %s",
346 mName, (long long)entry.timestamp, outputFormat->debugString().c_str());
Wonsik Kim3b4349a2020-11-10 11:54:15 -0800347 setFormat(outputFormat);
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700348 }
349
350 // Flushing mReorderStash because no other buffers should come after output
351 // EOS.
My Nameac29e592022-03-28 13:53:32 -0700352 if (entry.flags & BUFFER_FLAG_END_OF_STREAM) {
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700353 // Flush reorder stash
354 setReorderDepth(0);
355 }
356
357 if (!entry.notify) {
358 mPending.pop_front();
359 return DISCARD;
360 }
361
362 // Try to register the buffer.
363 status_t err = registerBuffer(*c2Buffer, index, outBuffer);
364 if (err != OK) {
365 if (err != WOULD_BLOCK) {
366 return REALLOCATE;
367 }
368 return RETRY;
369 }
370
371 // Append information from the front stash entry to outBuffer.
372 (*outBuffer)->meta()->setInt64("timeUs", entry.timestamp);
373 (*outBuffer)->meta()->setInt32("flags", entry.flags);
Byeongjo Park2eef13e2020-06-12 17:24:21 +0900374 (*outBuffer)->meta()->setInt64("frameIndex", entry.ordinal.frameIndex.peekll());
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700375 ALOGV("[%s] popFromStashAndRegister: "
376 "out buffer index = %zu [%p] => %p + %zu (%lld)",
377 mName, *index, outBuffer->get(),
378 (*outBuffer)->data(), (*outBuffer)->size(),
379 (long long)entry.timestamp);
380
381 // The front entry of mPending will be removed now that the registration
382 // succeeded.
383 mPending.pop_front();
384 return NOTIFY_CLIENT;
385}
386
387bool OutputBuffers::popPending(StashEntry *entry) {
388 if (mPending.empty()) {
389 return false;
390 }
391 *entry = mPending.front();
392 mPending.pop_front();
393 return true;
394}
395
396void OutputBuffers::deferPending(const OutputBuffers::StashEntry &entry) {
397 mPending.push_front(entry);
398}
399
400bool OutputBuffers::hasPending() const {
401 return !mPending.empty();
402}
403
404bool OutputBuffers::less(
405 const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2) const {
406 switch (mKey) {
407 case C2Config::ORDINAL: return o1.frameIndex < o2.frameIndex;
408 case C2Config::TIMESTAMP: return o1.timestamp < o2.timestamp;
409 case C2Config::CUSTOM: return o1.customOrdinal < o2.customOrdinal;
410 default:
411 ALOGD("Unrecognized key; default to timestamp");
412 return o1.frameIndex < o2.frameIndex;
413 }
414}
415
Wonsik Kim469c8342019-04-11 16:46:09 -0700416// LocalBufferPool
417
Wonsik Kim41d83432020-04-27 16:40:49 -0700418constexpr size_t kInitialPoolCapacity = kMaxLinearBufferSize;
419constexpr size_t kMaxPoolCapacity = kMaxLinearBufferSize * 32;
420
421std::shared_ptr<LocalBufferPool> LocalBufferPool::Create() {
422 return std::shared_ptr<LocalBufferPool>(new LocalBufferPool(kInitialPoolCapacity));
Wonsik Kim469c8342019-04-11 16:46:09 -0700423}
424
425sp<ABuffer> LocalBufferPool::newBuffer(size_t capacity) {
426 Mutex::Autolock lock(mMutex);
427 auto it = std::find_if(
428 mPool.begin(), mPool.end(),
429 [capacity](const std::vector<uint8_t> &vec) {
430 return vec.capacity() >= capacity;
431 });
432 if (it != mPool.end()) {
433 sp<ABuffer> buffer = new VectorBuffer(std::move(*it), shared_from_this());
434 mPool.erase(it);
435 return buffer;
436 }
437 if (mUsedSize + capacity > mPoolCapacity) {
438 while (!mPool.empty()) {
439 mUsedSize -= mPool.back().capacity();
440 mPool.pop_back();
441 }
Wonsik Kim41d83432020-04-27 16:40:49 -0700442 while (mUsedSize + capacity > mPoolCapacity && mPoolCapacity * 2 <= kMaxPoolCapacity) {
443 ALOGD("Increasing local buffer pool capacity from %zu to %zu",
444 mPoolCapacity, mPoolCapacity * 2);
445 mPoolCapacity *= 2;
446 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700447 if (mUsedSize + capacity > mPoolCapacity) {
448 ALOGD("mUsedSize = %zu, capacity = %zu, mPoolCapacity = %zu",
449 mUsedSize, capacity, mPoolCapacity);
450 return nullptr;
451 }
452 }
453 std::vector<uint8_t> vec(capacity);
454 mUsedSize += vec.capacity();
455 return new VectorBuffer(std::move(vec), shared_from_this());
456}
457
458LocalBufferPool::VectorBuffer::VectorBuffer(
459 std::vector<uint8_t> &&vec, const std::shared_ptr<LocalBufferPool> &pool)
460 : ABuffer(vec.data(), vec.capacity()),
461 mVec(std::move(vec)),
462 mPool(pool) {
463}
464
465LocalBufferPool::VectorBuffer::~VectorBuffer() {
466 std::shared_ptr<LocalBufferPool> pool = mPool.lock();
467 if (pool) {
468 // If pool is alive, return the vector back to the pool so that
469 // it can be recycled.
470 pool->returnVector(std::move(mVec));
471 }
472}
473
474void LocalBufferPool::returnVector(std::vector<uint8_t> &&vec) {
475 Mutex::Autolock lock(mMutex);
476 mPool.push_front(std::move(vec));
477}
478
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700479// FlexBuffersImpl
480
Wonsik Kim469c8342019-04-11 16:46:09 -0700481size_t FlexBuffersImpl::assignSlot(const sp<Codec2Buffer> &buffer) {
482 for (size_t i = 0; i < mBuffers.size(); ++i) {
483 if (mBuffers[i].clientBuffer == nullptr
484 && mBuffers[i].compBuffer.expired()) {
485 mBuffers[i].clientBuffer = buffer;
486 return i;
487 }
488 }
489 mBuffers.push_back({ buffer, std::weak_ptr<C2Buffer>() });
490 return mBuffers.size() - 1;
491}
492
Wonsik Kim469c8342019-04-11 16:46:09 -0700493bool FlexBuffersImpl::releaseSlot(
494 const sp<MediaCodecBuffer> &buffer,
495 std::shared_ptr<C2Buffer> *c2buffer,
496 bool release) {
497 sp<Codec2Buffer> clientBuffer;
498 size_t index = mBuffers.size();
499 for (size_t i = 0; i < mBuffers.size(); ++i) {
500 if (mBuffers[i].clientBuffer == buffer) {
501 clientBuffer = mBuffers[i].clientBuffer;
502 if (release) {
503 mBuffers[i].clientBuffer.clear();
504 }
505 index = i;
506 break;
507 }
508 }
509 if (clientBuffer == nullptr) {
510 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
511 return false;
512 }
513 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
514 if (!result) {
515 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700516 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700517 mBuffers[index].compBuffer = result;
518 }
519 if (c2buffer) {
520 *c2buffer = result;
521 }
522 return true;
523}
524
525bool FlexBuffersImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
526 for (size_t i = 0; i < mBuffers.size(); ++i) {
527 std::shared_ptr<C2Buffer> compBuffer =
528 mBuffers[i].compBuffer.lock();
529 if (!compBuffer || compBuffer != c2buffer) {
530 continue;
531 }
532 mBuffers[i].compBuffer.reset();
533 ALOGV("[%s] codec released buffer #%zu", mName, i);
534 return true;
535 }
536 ALOGV("[%s] codec released an unknown buffer", mName);
537 return false;
538}
539
540void FlexBuffersImpl::flush() {
541 ALOGV("[%s] buffers are flushed %zu", mName, mBuffers.size());
542 mBuffers.clear();
543}
544
Wonsik Kim0487b782020-10-28 11:45:50 -0700545size_t FlexBuffersImpl::numActiveSlots() const {
Wonsik Kim469c8342019-04-11 16:46:09 -0700546 return std::count_if(
547 mBuffers.begin(), mBuffers.end(),
548 [](const Entry &entry) {
Wonsik Kim0487b782020-10-28 11:45:50 -0700549 return (entry.clientBuffer != nullptr
550 || !entry.compBuffer.expired());
Wonsik Kim469c8342019-04-11 16:46:09 -0700551 });
552}
553
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700554size_t FlexBuffersImpl::numComponentBuffers() const {
555 return std::count_if(
556 mBuffers.begin(), mBuffers.end(),
557 [](const Entry &entry) {
558 return !entry.compBuffer.expired();
559 });
560}
561
Wonsik Kim469c8342019-04-11 16:46:09 -0700562// BuffersArrayImpl
563
564void BuffersArrayImpl::initialize(
565 const FlexBuffersImpl &impl,
566 size_t minSize,
567 std::function<sp<Codec2Buffer>()> allocate) {
568 mImplName = impl.mImplName + "[N]";
569 mName = mImplName.c_str();
570 for (size_t i = 0; i < impl.mBuffers.size(); ++i) {
571 sp<Codec2Buffer> clientBuffer = impl.mBuffers[i].clientBuffer;
572 bool ownedByClient = (clientBuffer != nullptr);
573 if (!ownedByClient) {
574 clientBuffer = allocate();
575 }
576 mBuffers.push_back({ clientBuffer, impl.mBuffers[i].compBuffer, ownedByClient });
577 }
578 ALOGV("[%s] converted %zu buffers to array mode of %zu", mName, mBuffers.size(), minSize);
579 for (size_t i = impl.mBuffers.size(); i < minSize; ++i) {
580 mBuffers.push_back({ allocate(), std::weak_ptr<C2Buffer>(), false });
581 }
582}
583
584status_t BuffersArrayImpl::grabBuffer(
585 size_t *index,
586 sp<Codec2Buffer> *buffer,
587 std::function<bool(const sp<Codec2Buffer> &)> match) {
588 // allBuffersDontMatch remains true if all buffers are available but
589 // match() returns false for every buffer.
590 bool allBuffersDontMatch = true;
591 for (size_t i = 0; i < mBuffers.size(); ++i) {
592 if (!mBuffers[i].ownedByClient && mBuffers[i].compBuffer.expired()) {
593 if (match(mBuffers[i].clientBuffer)) {
594 mBuffers[i].ownedByClient = true;
595 *buffer = mBuffers[i].clientBuffer;
596 (*buffer)->meta()->clear();
597 (*buffer)->setRange(0, (*buffer)->capacity());
598 *index = i;
599 return OK;
600 }
601 } else {
602 allBuffersDontMatch = false;
603 }
604 }
605 return allBuffersDontMatch ? NO_MEMORY : WOULD_BLOCK;
606}
607
608bool BuffersArrayImpl::returnBuffer(
609 const sp<MediaCodecBuffer> &buffer,
610 std::shared_ptr<C2Buffer> *c2buffer,
611 bool release) {
612 sp<Codec2Buffer> clientBuffer;
613 size_t index = mBuffers.size();
614 for (size_t i = 0; i < mBuffers.size(); ++i) {
615 if (mBuffers[i].clientBuffer == buffer) {
616 if (!mBuffers[i].ownedByClient) {
617 ALOGD("[%s] Client returned a buffer it does not own according to our record: %zu",
618 mName, i);
619 }
620 clientBuffer = mBuffers[i].clientBuffer;
621 if (release) {
622 mBuffers[i].ownedByClient = false;
623 }
624 index = i;
625 break;
626 }
627 }
628 if (clientBuffer == nullptr) {
629 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
630 return false;
631 }
632 ALOGV("[%s] %s: matching buffer found (index=%zu)", mName, __func__, index);
633 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
634 if (!result) {
635 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700636 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700637 mBuffers[index].compBuffer = result;
638 }
639 if (c2buffer) {
640 *c2buffer = result;
641 }
642 return true;
643}
644
645bool BuffersArrayImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
646 for (size_t i = 0; i < mBuffers.size(); ++i) {
647 std::shared_ptr<C2Buffer> compBuffer =
648 mBuffers[i].compBuffer.lock();
649 if (!compBuffer) {
650 continue;
651 }
652 if (c2buffer == compBuffer) {
653 if (mBuffers[i].ownedByClient) {
654 // This should not happen.
655 ALOGD("[%s] codec released a buffer owned by client "
656 "(index %zu)", mName, i);
657 }
658 mBuffers[i].compBuffer.reset();
659 ALOGV("[%s] codec released buffer #%zu(array mode)", mName, i);
660 return true;
661 }
662 }
663 ALOGV("[%s] codec released an unknown buffer (array mode)", mName);
664 return false;
665}
666
667void BuffersArrayImpl::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
668 array->clear();
669 for (const Entry &entry : mBuffers) {
670 array->push(entry.clientBuffer);
671 }
672}
673
674void BuffersArrayImpl::flush() {
675 for (Entry &entry : mBuffers) {
676 entry.ownedByClient = false;
677 }
678}
679
680void BuffersArrayImpl::realloc(std::function<sp<Codec2Buffer>()> alloc) {
681 size_t size = mBuffers.size();
682 mBuffers.clear();
683 for (size_t i = 0; i < size; ++i) {
684 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
685 }
686}
687
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700688void BuffersArrayImpl::grow(
689 size_t newSize, std::function<sp<Codec2Buffer>()> alloc) {
690 CHECK_LT(mBuffers.size(), newSize);
691 while (mBuffers.size() < newSize) {
692 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
693 }
694}
695
Wonsik Kim0487b782020-10-28 11:45:50 -0700696size_t BuffersArrayImpl::numActiveSlots() const {
Wonsik Kim469c8342019-04-11 16:46:09 -0700697 return std::count_if(
698 mBuffers.begin(), mBuffers.end(),
699 [](const Entry &entry) {
Wonsik Kim0487b782020-10-28 11:45:50 -0700700 return entry.ownedByClient || !entry.compBuffer.expired();
Wonsik Kim469c8342019-04-11 16:46:09 -0700701 });
702}
703
Wonsik Kima39882b2019-06-20 16:13:56 -0700704size_t BuffersArrayImpl::arraySize() const {
705 return mBuffers.size();
706}
707
Wonsik Kim469c8342019-04-11 16:46:09 -0700708// InputBuffersArray
709
710void InputBuffersArray::initialize(
711 const FlexBuffersImpl &impl,
712 size_t minSize,
713 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700714 mAllocate = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -0700715 mImpl.initialize(impl, minSize, allocate);
716}
717
718void InputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
719 mImpl.getArray(array);
720}
721
722bool InputBuffersArray::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
723 sp<Codec2Buffer> c2Buffer;
724 status_t err = mImpl.grabBuffer(index, &c2Buffer);
725 if (err == OK) {
726 c2Buffer->setFormat(mFormat);
727 handleImageData(c2Buffer);
728 *buffer = c2Buffer;
729 return true;
730 }
731 return false;
732}
733
734bool InputBuffersArray::releaseBuffer(
735 const sp<MediaCodecBuffer> &buffer,
736 std::shared_ptr<C2Buffer> *c2buffer,
737 bool release) {
738 return mImpl.returnBuffer(buffer, c2buffer, release);
739}
740
741bool InputBuffersArray::expireComponentBuffer(
742 const std::shared_ptr<C2Buffer> &c2buffer) {
743 return mImpl.expireComponentBuffer(c2buffer);
744}
745
746void InputBuffersArray::flush() {
747 mImpl.flush();
748}
749
Wonsik Kim0487b782020-10-28 11:45:50 -0700750size_t InputBuffersArray::numActiveSlots() const {
751 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700752}
753
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700754sp<Codec2Buffer> InputBuffersArray::createNewBuffer() {
755 return mAllocate();
756}
757
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800758// SlotInputBuffers
759
760bool SlotInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
761 sp<Codec2Buffer> newBuffer = createNewBuffer();
762 *index = mImpl.assignSlot(newBuffer);
763 *buffer = newBuffer;
764 return true;
765}
766
767bool SlotInputBuffers::releaseBuffer(
768 const sp<MediaCodecBuffer> &buffer,
769 std::shared_ptr<C2Buffer> *c2buffer,
770 bool release) {
771 return mImpl.releaseSlot(buffer, c2buffer, release);
772}
773
774bool SlotInputBuffers::expireComponentBuffer(
775 const std::shared_ptr<C2Buffer> &c2buffer) {
776 return mImpl.expireComponentBuffer(c2buffer);
777}
778
779void SlotInputBuffers::flush() {
780 mImpl.flush();
781}
782
783std::unique_ptr<InputBuffers> SlotInputBuffers::toArrayMode(size_t) {
784 TRESPASS("Array mode should not be called at non-legacy mode");
785 return nullptr;
786}
787
Wonsik Kim0487b782020-10-28 11:45:50 -0700788size_t SlotInputBuffers::numActiveSlots() const {
789 return mImpl.numActiveSlots();
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800790}
791
792sp<Codec2Buffer> SlotInputBuffers::createNewBuffer() {
793 return new DummyContainerBuffer{mFormat, nullptr};
794}
795
Wonsik Kim469c8342019-04-11 16:46:09 -0700796// LinearInputBuffers
797
798bool LinearInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700799 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700800 if (newBuffer == nullptr) {
801 return false;
802 }
803 *index = mImpl.assignSlot(newBuffer);
804 *buffer = newBuffer;
805 return true;
806}
807
808bool LinearInputBuffers::releaseBuffer(
809 const sp<MediaCodecBuffer> &buffer,
810 std::shared_ptr<C2Buffer> *c2buffer,
811 bool release) {
812 return mImpl.releaseSlot(buffer, c2buffer, release);
813}
814
815bool LinearInputBuffers::expireComponentBuffer(
816 const std::shared_ptr<C2Buffer> &c2buffer) {
817 return mImpl.expireComponentBuffer(c2buffer);
818}
819
820void LinearInputBuffers::flush() {
821 // This is no-op by default unless we're in array mode where we need to keep
822 // track of the flushed work.
823 mImpl.flush();
824}
825
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700826std::unique_ptr<InputBuffers> LinearInputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700827 std::unique_ptr<InputBuffersArray> array(
828 new InputBuffersArray(mComponentName.c_str(), "1D-Input[N]"));
829 array->setPool(mPool);
830 array->setFormat(mFormat);
831 array->initialize(
832 mImpl,
833 size,
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700834 [pool = mPool, format = mFormat] () -> sp<Codec2Buffer> {
835 return Alloc(pool, format);
836 });
Wonsik Kim469c8342019-04-11 16:46:09 -0700837 return std::move(array);
838}
839
Wonsik Kim0487b782020-10-28 11:45:50 -0700840size_t LinearInputBuffers::numActiveSlots() const {
841 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700842}
843
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700844// static
845sp<Codec2Buffer> LinearInputBuffers::Alloc(
846 const std::shared_ptr<C2BlockPool> &pool, const sp<AMessage> &format) {
847 int32_t capacity = kLinearBufferSize;
848 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
849 if ((size_t)capacity > kMaxLinearBufferSize) {
850 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
851 capacity = kMaxLinearBufferSize;
852 }
853
Wonsik Kim666604a2020-05-14 16:57:49 -0700854 int64_t usageValue = 0;
855 (void)format->findInt64("android._C2MemoryUsage", &usageValue);
856 C2MemoryUsage usage{usageValue | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE};
Wonsik Kim469c8342019-04-11 16:46:09 -0700857 std::shared_ptr<C2LinearBlock> block;
858
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700859 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700860 if (err != C2_OK) {
861 return nullptr;
862 }
863
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700864 return LinearBlockBuffer::Allocate(format, block);
865}
866
867sp<Codec2Buffer> LinearInputBuffers::createNewBuffer() {
868 return Alloc(mPool, mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -0700869}
870
871// EncryptedLinearInputBuffers
872
873EncryptedLinearInputBuffers::EncryptedLinearInputBuffers(
874 bool secure,
875 const sp<MemoryDealer> &dealer,
876 const sp<ICrypto> &crypto,
877 int32_t heapSeqNum,
878 size_t capacity,
879 size_t numInputSlots,
880 const char *componentName, const char *name)
881 : LinearInputBuffers(componentName, name),
882 mUsage({0, 0}),
883 mDealer(dealer),
884 mCrypto(crypto),
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700885 mMemoryVector(new std::vector<Entry>){
Wonsik Kim469c8342019-04-11 16:46:09 -0700886 if (secure) {
887 mUsage = { C2MemoryUsage::READ_PROTECTED, 0 };
888 } else {
889 mUsage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
890 }
891 for (size_t i = 0; i < numInputSlots; ++i) {
892 sp<IMemory> memory = mDealer->allocate(capacity);
893 if (memory == nullptr) {
894 ALOGD("[%s] Failed to allocate memory from dealer: only %zu slots allocated",
895 mName, i);
896 break;
897 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700898 mMemoryVector->push_back({std::weak_ptr<C2LinearBlock>(), memory, heapSeqNum});
Wonsik Kim469c8342019-04-11 16:46:09 -0700899 }
900}
901
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700902std::unique_ptr<InputBuffers> EncryptedLinearInputBuffers::toArrayMode(size_t size) {
903 std::unique_ptr<InputBuffersArray> array(
904 new InputBuffersArray(mComponentName.c_str(), "1D-EncryptedInput[N]"));
905 array->setPool(mPool);
906 array->setFormat(mFormat);
907 array->initialize(
908 mImpl,
909 size,
910 [pool = mPool,
911 format = mFormat,
912 usage = mUsage,
913 memoryVector = mMemoryVector] () -> sp<Codec2Buffer> {
914 return Alloc(pool, format, usage, memoryVector);
915 });
916 return std::move(array);
917}
918
919
920// static
921sp<Codec2Buffer> EncryptedLinearInputBuffers::Alloc(
922 const std::shared_ptr<C2BlockPool> &pool,
923 const sp<AMessage> &format,
924 C2MemoryUsage usage,
925 const std::shared_ptr<std::vector<EncryptedLinearInputBuffers::Entry>> &memoryVector) {
926 int32_t capacity = kLinearBufferSize;
927 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
928 if ((size_t)capacity > kMaxLinearBufferSize) {
929 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
930 capacity = kMaxLinearBufferSize;
931 }
932
Wonsik Kim469c8342019-04-11 16:46:09 -0700933 sp<IMemory> memory;
934 size_t slot = 0;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700935 int32_t heapSeqNum = -1;
936 for (; slot < memoryVector->size(); ++slot) {
937 if (memoryVector->at(slot).block.expired()) {
938 memory = memoryVector->at(slot).memory;
939 heapSeqNum = memoryVector->at(slot).heapSeqNum;
Wonsik Kim469c8342019-04-11 16:46:09 -0700940 break;
941 }
942 }
943 if (memory == nullptr) {
944 return nullptr;
945 }
946
David Stevens94b608f2021-07-29 15:04:14 +0900947 int64_t usageValue = 0;
948 (void)format->findInt64("android._C2MemoryUsage", &usageValue);
949 usage = C2MemoryUsage(usage.expected | usageValue);
950
Wonsik Kim469c8342019-04-11 16:46:09 -0700951 std::shared_ptr<C2LinearBlock> block;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700952 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700953 if (err != C2_OK || block == nullptr) {
954 return nullptr;
955 }
956
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700957 memoryVector->at(slot).block = block;
958 return new EncryptedLinearBlockBuffer(format, block, memory, heapSeqNum);
959}
960
961sp<Codec2Buffer> EncryptedLinearInputBuffers::createNewBuffer() {
962 // TODO: android_2020
963 return nullptr;
Wonsik Kim469c8342019-04-11 16:46:09 -0700964}
965
966// GraphicMetadataInputBuffers
967
968GraphicMetadataInputBuffers::GraphicMetadataInputBuffers(
969 const char *componentName, const char *name)
970 : InputBuffers(componentName, name),
971 mImpl(mName),
972 mStore(GetCodec2PlatformAllocatorStore()) { }
973
974bool GraphicMetadataInputBuffers::requestNewBuffer(
975 size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700976 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700977 if (newBuffer == nullptr) {
978 return false;
979 }
980 *index = mImpl.assignSlot(newBuffer);
981 *buffer = newBuffer;
982 return true;
983}
984
985bool GraphicMetadataInputBuffers::releaseBuffer(
986 const sp<MediaCodecBuffer> &buffer,
987 std::shared_ptr<C2Buffer> *c2buffer,
988 bool release) {
989 return mImpl.releaseSlot(buffer, c2buffer, release);
990}
991
992bool GraphicMetadataInputBuffers::expireComponentBuffer(
993 const std::shared_ptr<C2Buffer> &c2buffer) {
994 return mImpl.expireComponentBuffer(c2buffer);
995}
996
997void GraphicMetadataInputBuffers::flush() {
998 // This is no-op by default unless we're in array mode where we need to keep
999 // track of the flushed work.
1000}
1001
1002std::unique_ptr<InputBuffers> GraphicMetadataInputBuffers::toArrayMode(
1003 size_t size) {
1004 std::shared_ptr<C2Allocator> alloc;
1005 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
1006 if (err != C2_OK) {
1007 return nullptr;
1008 }
1009 std::unique_ptr<InputBuffersArray> array(
1010 new InputBuffersArray(mComponentName.c_str(), "2D-MetaInput[N]"));
1011 array->setPool(mPool);
1012 array->setFormat(mFormat);
1013 array->initialize(
1014 mImpl,
1015 size,
1016 [format = mFormat, alloc]() -> sp<Codec2Buffer> {
1017 return new GraphicMetadataBuffer(format, alloc);
1018 });
1019 return std::move(array);
1020}
1021
Wonsik Kim0487b782020-10-28 11:45:50 -07001022size_t GraphicMetadataInputBuffers::numActiveSlots() const {
1023 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001024}
1025
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001026sp<Codec2Buffer> GraphicMetadataInputBuffers::createNewBuffer() {
1027 std::shared_ptr<C2Allocator> alloc;
1028 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
1029 if (err != C2_OK) {
1030 return nullptr;
1031 }
1032 return new GraphicMetadataBuffer(mFormat, alloc);
1033}
1034
Wonsik Kim469c8342019-04-11 16:46:09 -07001035// GraphicInputBuffers
1036
1037GraphicInputBuffers::GraphicInputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -07001038 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -07001039 : InputBuffers(componentName, name),
1040 mImpl(mName),
Wonsik Kim41d83432020-04-27 16:40:49 -07001041 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -07001042
1043bool GraphicInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001044 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -07001045 if (newBuffer == nullptr) {
1046 return false;
1047 }
1048 *index = mImpl.assignSlot(newBuffer);
1049 handleImageData(newBuffer);
1050 *buffer = newBuffer;
1051 return true;
1052}
1053
1054bool GraphicInputBuffers::releaseBuffer(
1055 const sp<MediaCodecBuffer> &buffer,
1056 std::shared_ptr<C2Buffer> *c2buffer,
1057 bool release) {
1058 return mImpl.releaseSlot(buffer, c2buffer, release);
1059}
1060
1061bool GraphicInputBuffers::expireComponentBuffer(
1062 const std::shared_ptr<C2Buffer> &c2buffer) {
1063 return mImpl.expireComponentBuffer(c2buffer);
1064}
1065
1066void GraphicInputBuffers::flush() {
1067 // This is no-op by default unless we're in array mode where we need to keep
1068 // track of the flushed work.
1069}
1070
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001071static uint32_t extractPixelFormat(const sp<AMessage> &format) {
1072 int32_t frameworkColorFormat = 0;
1073 if (!format->findInt32("android._color-format", &frameworkColorFormat)) {
1074 return PIXEL_FORMAT_UNKNOWN;
1075 }
1076 uint32_t pixelFormat = PIXEL_FORMAT_UNKNOWN;
1077 if (C2Mapper::mapPixelFormatFrameworkToCodec(frameworkColorFormat, &pixelFormat)) {
1078 return pixelFormat;
1079 }
1080 return PIXEL_FORMAT_UNKNOWN;
1081}
1082
Wonsik Kim469c8342019-04-11 16:46:09 -07001083std::unique_ptr<InputBuffers> GraphicInputBuffers::toArrayMode(size_t size) {
1084 std::unique_ptr<InputBuffersArray> array(
1085 new InputBuffersArray(mComponentName.c_str(), "2D-BB-Input[N]"));
1086 array->setPool(mPool);
1087 array->setFormat(mFormat);
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001088 uint32_t pixelFormat = extractPixelFormat(mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -07001089 array->initialize(
1090 mImpl,
1091 size,
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001092 [pool = mPool, format = mFormat, lbp = mLocalBufferPool, pixelFormat]()
1093 -> sp<Codec2Buffer> {
Wonsik Kim469c8342019-04-11 16:46:09 -07001094 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
David Stevens94b608f2021-07-29 15:04:14 +09001095 return AllocateInputGraphicBuffer(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001096 pool, format, pixelFormat, usage, lbp);
Wonsik Kim469c8342019-04-11 16:46:09 -07001097 });
1098 return std::move(array);
1099}
1100
Wonsik Kim0487b782020-10-28 11:45:50 -07001101size_t GraphicInputBuffers::numActiveSlots() const {
1102 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001103}
1104
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001105sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
David Stevens94b608f2021-07-29 15:04:14 +09001106 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
1107 return AllocateInputGraphicBuffer(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001108 mPool, mFormat, extractPixelFormat(mFormat), usage, mLocalBufferPool);
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001109}
1110
Wonsik Kim469c8342019-04-11 16:46:09 -07001111// OutputBuffersArray
1112
1113void OutputBuffersArray::initialize(
1114 const FlexBuffersImpl &impl,
1115 size_t minSize,
1116 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001117 mAlloc = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -07001118 mImpl.initialize(impl, minSize, allocate);
1119}
1120
1121status_t OutputBuffersArray::registerBuffer(
1122 const std::shared_ptr<C2Buffer> &buffer,
1123 size_t *index,
1124 sp<MediaCodecBuffer> *clientBuffer) {
1125 sp<Codec2Buffer> c2Buffer;
1126 status_t err = mImpl.grabBuffer(
1127 index,
1128 &c2Buffer,
1129 [buffer](const sp<Codec2Buffer> &clientBuffer) {
1130 return clientBuffer->canCopy(buffer);
1131 });
1132 if (err == WOULD_BLOCK) {
1133 ALOGV("[%s] buffers temporarily not available", mName);
1134 return err;
1135 } else if (err != OK) {
1136 ALOGD("[%s] grabBuffer failed: %d", mName, err);
1137 return err;
1138 }
1139 c2Buffer->setFormat(mFormat);
Wonsik Kim6f23cfc2021-09-24 05:45:52 -07001140 if (!convert(buffer, &c2Buffer) && !c2Buffer->copy(buffer)) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001141 ALOGD("[%s] copy buffer failed", mName);
1142 return WOULD_BLOCK;
1143 }
1144 submit(c2Buffer);
1145 handleImageData(c2Buffer);
1146 *clientBuffer = c2Buffer;
1147 ALOGV("[%s] grabbed buffer %zu", mName, *index);
1148 return OK;
1149}
1150
1151status_t OutputBuffersArray::registerCsd(
1152 const C2StreamInitDataInfo::output *csd,
1153 size_t *index,
1154 sp<MediaCodecBuffer> *clientBuffer) {
1155 sp<Codec2Buffer> c2Buffer;
1156 status_t err = mImpl.grabBuffer(
1157 index,
1158 &c2Buffer,
1159 [csd](const sp<Codec2Buffer> &clientBuffer) {
1160 return clientBuffer->base() != nullptr
1161 && clientBuffer->capacity() >= csd->flexCount();
1162 });
1163 if (err != OK) {
1164 return err;
1165 }
1166 memcpy(c2Buffer->base(), csd->m.value, csd->flexCount());
1167 c2Buffer->setRange(0, csd->flexCount());
1168 c2Buffer->setFormat(mFormat);
1169 *clientBuffer = c2Buffer;
1170 return OK;
1171}
1172
1173bool OutputBuffersArray::releaseBuffer(
1174 const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) {
1175 return mImpl.returnBuffer(buffer, c2buffer, true);
1176}
1177
1178void OutputBuffersArray::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1179 (void)flushedWork;
1180 mImpl.flush();
1181 if (mSkipCutBuffer != nullptr) {
1182 mSkipCutBuffer->clear();
1183 }
1184}
1185
1186void OutputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
1187 mImpl.getArray(array);
1188}
1189
Wonsik Kim0487b782020-10-28 11:45:50 -07001190size_t OutputBuffersArray::numActiveSlots() const {
1191 return mImpl.numActiveSlots();
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001192}
1193
Wonsik Kim469c8342019-04-11 16:46:09 -07001194void OutputBuffersArray::realloc(const std::shared_ptr<C2Buffer> &c2buffer) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001195 switch (c2buffer->data().type()) {
1196 case C2BufferData::LINEAR: {
1197 uint32_t size = kLinearBufferSize;
Nick Desaulniersd09eaea2019-10-07 20:19:39 -07001198 const std::vector<C2ConstLinearBlock> &linear_blocks = c2buffer->data().linearBlocks();
1199 const uint32_t block_size = linear_blocks.front().size();
1200 if (block_size < kMaxLinearBufferSize / 2) {
1201 size = block_size * 2;
Wonsik Kim469c8342019-04-11 16:46:09 -07001202 } else {
1203 size = kMaxLinearBufferSize;
1204 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001205 mAlloc = [format = mFormat, size] {
Wonsik Kim469c8342019-04-11 16:46:09 -07001206 return new LocalLinearBuffer(format, new ABuffer(size));
1207 };
Wonsik Kima39882b2019-06-20 16:13:56 -07001208 ALOGD("[%s] reallocating with linear buffer of size %u", mName, size);
Wonsik Kim469c8342019-04-11 16:46:09 -07001209 break;
1210 }
1211
Wonsik Kima39882b2019-06-20 16:13:56 -07001212 case C2BufferData::GRAPHIC: {
1213 // This is only called for RawGraphicOutputBuffers.
1214 mAlloc = [format = mFormat,
Wonsik Kim41d83432020-04-27 16:40:49 -07001215 lbp = LocalBufferPool::Create()] {
Wonsik Kima39882b2019-06-20 16:13:56 -07001216 return ConstGraphicBlockBuffer::AllocateEmpty(
1217 format,
1218 [lbp](size_t capacity) {
1219 return lbp->newBuffer(capacity);
1220 });
1221 };
1222 ALOGD("[%s] reallocating with graphic buffer: format = %s",
1223 mName, mFormat->debugString().c_str());
1224 break;
1225 }
Wonsik Kim469c8342019-04-11 16:46:09 -07001226
1227 case C2BufferData::INVALID: [[fallthrough]];
1228 case C2BufferData::LINEAR_CHUNKS: [[fallthrough]];
1229 case C2BufferData::GRAPHIC_CHUNKS: [[fallthrough]];
1230 default:
1231 ALOGD("Unsupported type: %d", (int)c2buffer->data().type());
1232 return;
1233 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001234 mImpl.realloc(mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -07001235}
1236
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001237void OutputBuffersArray::grow(size_t newSize) {
1238 mImpl.grow(newSize, mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -07001239}
1240
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001241void OutputBuffersArray::transferFrom(OutputBuffers* source) {
1242 mFormat = source->mFormat;
1243 mSkipCutBuffer = source->mSkipCutBuffer;
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001244 mPending = std::move(source->mPending);
1245 mReorderStash = std::move(source->mReorderStash);
1246 mDepth = source->mDepth;
1247 mKey = source->mKey;
1248}
1249
Wonsik Kim469c8342019-04-11 16:46:09 -07001250// FlexOutputBuffers
1251
1252status_t FlexOutputBuffers::registerBuffer(
1253 const std::shared_ptr<C2Buffer> &buffer,
1254 size_t *index,
1255 sp<MediaCodecBuffer> *clientBuffer) {
Wonsik Kim6f23cfc2021-09-24 05:45:52 -07001256 sp<Codec2Buffer> newBuffer;
1257 if (!convert(buffer, &newBuffer)) {
1258 newBuffer = wrap(buffer);
1259 if (newBuffer == nullptr) {
1260 return NO_MEMORY;
1261 }
Wonsik Kim469c8342019-04-11 16:46:09 -07001262 }
1263 newBuffer->setFormat(mFormat);
1264 *index = mImpl.assignSlot(newBuffer);
1265 handleImageData(newBuffer);
1266 *clientBuffer = newBuffer;
1267 ALOGV("[%s] registered buffer %zu", mName, *index);
1268 return OK;
1269}
1270
1271status_t FlexOutputBuffers::registerCsd(
1272 const C2StreamInitDataInfo::output *csd,
1273 size_t *index,
1274 sp<MediaCodecBuffer> *clientBuffer) {
1275 sp<Codec2Buffer> newBuffer = new LocalLinearBuffer(
1276 mFormat, ABuffer::CreateAsCopy(csd->m.value, csd->flexCount()));
1277 *index = mImpl.assignSlot(newBuffer);
1278 *clientBuffer = newBuffer;
1279 return OK;
1280}
1281
1282bool FlexOutputBuffers::releaseBuffer(
1283 const sp<MediaCodecBuffer> &buffer,
1284 std::shared_ptr<C2Buffer> *c2buffer) {
1285 return mImpl.releaseSlot(buffer, c2buffer, true);
1286}
1287
1288void FlexOutputBuffers::flush(
1289 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1290 (void) flushedWork;
1291 // This is no-op by default unless we're in array mode where we need to keep
1292 // track of the flushed work.
1293}
1294
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001295std::unique_ptr<OutputBuffersArray> FlexOutputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001296 std::unique_ptr<OutputBuffersArray> array(new OutputBuffersArray(mComponentName.c_str()));
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001297 array->transferFrom(this);
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001298 std::function<sp<Codec2Buffer>()> alloc = getAlloc();
1299 array->initialize(mImpl, size, alloc);
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001300 return array;
Wonsik Kim469c8342019-04-11 16:46:09 -07001301}
1302
Wonsik Kim0487b782020-10-28 11:45:50 -07001303size_t FlexOutputBuffers::numActiveSlots() const {
1304 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001305}
1306
1307// LinearOutputBuffers
1308
1309void LinearOutputBuffers::flush(
1310 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1311 if (mSkipCutBuffer != nullptr) {
1312 mSkipCutBuffer->clear();
1313 }
1314 FlexOutputBuffers::flush(flushedWork);
1315}
1316
1317sp<Codec2Buffer> LinearOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1318 if (buffer == nullptr) {
1319 ALOGV("[%s] using a dummy buffer", mName);
1320 return new LocalLinearBuffer(mFormat, new ABuffer(0));
1321 }
1322 if (buffer->data().type() != C2BufferData::LINEAR) {
1323 ALOGV("[%s] non-linear buffer %d", mName, buffer->data().type());
1324 // We expect linear output buffers from the component.
1325 return nullptr;
1326 }
1327 if (buffer->data().linearBlocks().size() != 1u) {
1328 ALOGV("[%s] no linear buffers", mName);
1329 // We expect one and only one linear block from the component.
1330 return nullptr;
1331 }
1332 sp<Codec2Buffer> clientBuffer = ConstLinearBlockBuffer::Allocate(mFormat, buffer);
1333 if (clientBuffer == nullptr) {
1334 ALOGD("[%s] ConstLinearBlockBuffer::Allocate failed", mName);
1335 return nullptr;
1336 }
1337 submit(clientBuffer);
1338 return clientBuffer;
1339}
1340
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001341std::function<sp<Codec2Buffer>()> LinearOutputBuffers::getAlloc() {
1342 return [format = mFormat]{
1343 // TODO: proper max output size
1344 return new LocalLinearBuffer(format, new ABuffer(kLinearBufferSize));
1345 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001346}
1347
1348// GraphicOutputBuffers
1349
1350sp<Codec2Buffer> GraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1351 return new DummyContainerBuffer(mFormat, buffer);
1352}
1353
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001354std::function<sp<Codec2Buffer>()> GraphicOutputBuffers::getAlloc() {
1355 return [format = mFormat]{
1356 return new DummyContainerBuffer(format);
1357 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001358}
1359
1360// RawGraphicOutputBuffers
1361
1362RawGraphicOutputBuffers::RawGraphicOutputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -07001363 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -07001364 : FlexOutputBuffers(componentName, name),
Wonsik Kim41d83432020-04-27 16:40:49 -07001365 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -07001366
1367sp<Codec2Buffer> RawGraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1368 if (buffer == nullptr) {
Wonsik Kim6f116902021-07-14 08:58:07 -07001369 return new Codec2Buffer(mFormat, new ABuffer(nullptr, 0));
Wonsik Kim469c8342019-04-11 16:46:09 -07001370 } else {
1371 return ConstGraphicBlockBuffer::Allocate(
1372 mFormat,
1373 buffer,
1374 [lbp = mLocalBufferPool](size_t capacity) {
1375 return lbp->newBuffer(capacity);
1376 });
1377 }
1378}
1379
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001380std::function<sp<Codec2Buffer>()> RawGraphicOutputBuffers::getAlloc() {
1381 return [format = mFormat, lbp = mLocalBufferPool]{
1382 return ConstGraphicBlockBuffer::AllocateEmpty(
1383 format,
1384 [lbp](size_t capacity) {
1385 return lbp->newBuffer(capacity);
1386 });
1387 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001388}
1389
1390} // namespace android