blob: d57eb0c91b70bb51cedaf83c89b5ec7ec7087af0 [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>
Pawin Vongmasa9b906982020-04-11 05:07:15 -070025#include <media/stagefright/MediaCodec.h>
Wonsik Kim469c8342019-04-11 16:46:09 -070026#include <media/stagefright/MediaCodecConstants.h>
Wonsik Kim155d5cb2019-10-09 12:49:49 -070027#include <media/stagefright/SkipCutBuffer.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070028#include <mediadrm/ICrypto.h>
Wonsik Kim469c8342019-04-11 16:46:09 -070029
30#include "CCodecBuffers.h"
Wonsik Kimd79ee1f2020-08-27 17:41:56 -070031#include "Codec2Mapper.h"
Wonsik Kim469c8342019-04-11 16:46:09 -070032
33namespace android {
34
35namespace {
36
37sp<GraphicBlockBuffer> AllocateGraphicBuffer(
38 const std::shared_ptr<C2BlockPool> &pool,
39 const sp<AMessage> &format,
40 uint32_t pixelFormat,
41 const C2MemoryUsage &usage,
42 const std::shared_ptr<LocalBufferPool> &localBufferPool) {
43 int32_t width, height;
44 if (!format->findInt32("width", &width) || !format->findInt32("height", &height)) {
45 ALOGD("format lacks width or height");
46 return nullptr;
47 }
48
49 std::shared_ptr<C2GraphicBlock> block;
50 c2_status_t err = pool->fetchGraphicBlock(
51 width, height, pixelFormat, usage, &block);
52 if (err != C2_OK) {
53 ALOGD("fetch graphic block failed: %d", err);
54 return nullptr;
55 }
56
57 return GraphicBlockBuffer::Allocate(
58 format,
59 block,
60 [localBufferPool](size_t capacity) {
61 return localBufferPool->newBuffer(capacity);
62 });
63}
64
65} // namespace
66
67// CCodecBuffers
68
69void CCodecBuffers::setFormat(const sp<AMessage> &format) {
70 CHECK(format != nullptr);
71 mFormat = format;
72}
73
74sp<AMessage> CCodecBuffers::dupFormat() {
75 return mFormat != nullptr ? mFormat->dup() : nullptr;
76}
77
78void CCodecBuffers::handleImageData(const sp<Codec2Buffer> &buffer) {
79 sp<ABuffer> imageDataCandidate = buffer->getImageData();
80 if (imageDataCandidate == nullptr) {
Wonsik Kim4a3c0462021-03-09 15:45:05 -080081 if (mFormatWithImageData) {
82 // We previously sent the format with image data, so use the same format.
83 buffer->setFormat(mFormatWithImageData);
84 }
Wonsik Kim469c8342019-04-11 16:46:09 -070085 return;
86 }
Wonsik Kim4a3c0462021-03-09 15:45:05 -080087 if (!mLastImageData
88 || imageDataCandidate->size() != mLastImageData->size()
89 || memcmp(imageDataCandidate->data(),
90 mLastImageData->data(),
91 mLastImageData->size()) != 0) {
Wonsik Kim469c8342019-04-11 16:46:09 -070092 ALOGD("[%s] updating image-data", mName);
Wonsik Kim4a3c0462021-03-09 15:45:05 -080093 mFormatWithImageData = dupFormat();
94 mLastImageData = imageDataCandidate;
95 mFormatWithImageData->setBuffer("image-data", imageDataCandidate);
Wonsik Kim469c8342019-04-11 16:46:09 -070096 MediaImage2 *img = (MediaImage2*)imageDataCandidate->data();
97 if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
98 int32_t stride = img->mPlane[0].mRowInc;
Wonsik Kim4a3c0462021-03-09 15:45:05 -080099 mFormatWithImageData->setInt32(KEY_STRIDE, stride);
Wonsik Kim469c8342019-04-11 16:46:09 -0700100 ALOGD("[%s] updating stride = %d", mName, stride);
101 if (img->mNumPlanes > 1 && stride > 0) {
Taehwan Kimfd9b8092020-09-17 12:26:40 +0900102 int64_t offsetDelta =
103 (int64_t)img->mPlane[1].mOffset - (int64_t)img->mPlane[0].mOffset;
104 int32_t vstride = int32_t(offsetDelta / stride);
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800105 mFormatWithImageData->setInt32(KEY_SLICE_HEIGHT, vstride);
Wonsik Kim469c8342019-04-11 16:46:09 -0700106 ALOGD("[%s] updating vstride = %d", mName, vstride);
Wonsik Kim2eb06312020-12-03 11:07:58 -0800107 buffer->setRange(
108 img->mPlane[0].mOffset,
109 buffer->size() - img->mPlane[0].mOffset);
Wonsik Kim469c8342019-04-11 16:46:09 -0700110 }
111 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700112 }
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800113 buffer->setFormat(mFormatWithImageData);
Wonsik Kim469c8342019-04-11 16:46:09 -0700114}
115
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700116// InputBuffers
117
118sp<Codec2Buffer> InputBuffers::cloneAndReleaseBuffer(const sp<MediaCodecBuffer> &buffer) {
119 sp<Codec2Buffer> copy = createNewBuffer();
120 if (copy == nullptr) {
121 return nullptr;
122 }
123 std::shared_ptr<C2Buffer> c2buffer;
124 if (!releaseBuffer(buffer, &c2buffer, true)) {
125 return nullptr;
126 }
127 if (!copy->canCopy(c2buffer)) {
128 return nullptr;
129 }
130 if (!copy->copy(c2buffer)) {
131 return nullptr;
132 }
Wonsik Kimfb5ca492021-08-11 14:18:19 -0700133 copy->meta()->extend(buffer->meta());
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700134 return copy;
135}
136
Wonsik Kim469c8342019-04-11 16:46:09 -0700137// OutputBuffers
138
Wonsik Kim41d83432020-04-27 16:40:49 -0700139OutputBuffers::OutputBuffers(const char *componentName, const char *name)
140 : CCodecBuffers(componentName, name) { }
141
142OutputBuffers::~OutputBuffers() = default;
143
Wonsik Kim469c8342019-04-11 16:46:09 -0700144void OutputBuffers::initSkipCutBuffer(
145 int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount) {
146 CHECK(mSkipCutBuffer == nullptr);
147 mDelay = delay;
148 mPadding = padding;
149 mSampleRate = sampleRate;
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700150 mChannelCount = channelCount;
151 setSkipCutBuffer(delay, padding);
Wonsik Kim469c8342019-04-11 16:46:09 -0700152}
153
154void OutputBuffers::updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount) {
155 if (mSkipCutBuffer == nullptr) {
156 return;
157 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700158 if (mSampleRate == sampleRate && mChannelCount == channelCount) {
159 return;
160 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700161 int32_t delay = mDelay;
162 int32_t padding = mPadding;
163 if (sampleRate != mSampleRate) {
164 delay = ((int64_t)delay * sampleRate) / mSampleRate;
165 padding = ((int64_t)padding * sampleRate) / mSampleRate;
166 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700167 mSampleRate = sampleRate;
168 mChannelCount = channelCount;
169 setSkipCutBuffer(delay, padding);
Wonsik Kim469c8342019-04-11 16:46:09 -0700170}
171
Wonsik Kim970bf0b2020-11-10 11:54:15 -0800172void OutputBuffers::updateSkipCutBuffer(const sp<AMessage> &format) {
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700173 AString mediaType;
174 if (format->findString(KEY_MIME, &mediaType)
175 && mediaType == MIMETYPE_AUDIO_RAW) {
176 int32_t channelCount;
177 int32_t sampleRate;
178 if (format->findInt32(KEY_CHANNEL_COUNT, &channelCount)
179 && format->findInt32(KEY_SAMPLE_RATE, &sampleRate)) {
180 updateSkipCutBuffer(sampleRate, channelCount);
181 }
182 }
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700183}
184
Wonsik Kim469c8342019-04-11 16:46:09 -0700185void OutputBuffers::submit(const sp<MediaCodecBuffer> &buffer) {
186 if (mSkipCutBuffer != nullptr) {
187 mSkipCutBuffer->submit(buffer);
188 }
189}
190
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700191void OutputBuffers::setSkipCutBuffer(int32_t skip, int32_t cut) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700192 if (mSkipCutBuffer != nullptr) {
193 size_t prevSize = mSkipCutBuffer->size();
194 if (prevSize != 0u) {
195 ALOGD("[%s] Replacing SkipCutBuffer holding %zu bytes", mName, prevSize);
196 }
197 }
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700198 mSkipCutBuffer = new SkipCutBuffer(skip, cut, mChannelCount);
Wonsik Kim469c8342019-04-11 16:46:09 -0700199}
200
Wonsik Kim6f23cfc2021-09-24 05:45:52 -0700201bool OutputBuffers::convert(
202 const std::shared_ptr<C2Buffer> &src, sp<Codec2Buffer> *dst) {
203 if (!src || src->data().type() != C2BufferData::LINEAR) {
204 return false;
205 }
206 int32_t configEncoding = kAudioEncodingPcm16bit;
207 int32_t codecEncoding = kAudioEncodingPcm16bit;
208 if (mFormat->findInt32("android._codec-pcm-encoding", &codecEncoding)
209 && mFormat->findInt32("android._config-pcm-encoding", &configEncoding)) {
210 if (mSrcEncoding != codecEncoding || mDstEncoding != configEncoding) {
211 if (codecEncoding != configEncoding) {
212 mDataConverter = AudioConverter::Create(
213 (AudioEncoding)codecEncoding, (AudioEncoding)configEncoding);
214 ALOGD_IF(mDataConverter, "[%s] Converter created from %d to %d",
215 mName, codecEncoding, configEncoding);
216 mFormatWithConverter = mFormat->dup();
217 mFormatWithConverter->setInt32(KEY_PCM_ENCODING, configEncoding);
218 } else {
219 mDataConverter = nullptr;
220 mFormatWithConverter = nullptr;
221 }
222 mSrcEncoding = codecEncoding;
223 mDstEncoding = configEncoding;
224 }
225 if (int encoding; !mFormat->findInt32(KEY_PCM_ENCODING, &encoding)
226 || encoding != mDstEncoding) {
227 }
228 }
229 if (!mDataConverter) {
230 return false;
231 }
232 sp<MediaCodecBuffer> srcBuffer = ConstLinearBlockBuffer::Allocate(mFormat, src);
233 if (!srcBuffer) {
234 return false;
235 }
Greg Kaiser92dc4542021-10-08 06:58:19 -0700236 if (!*dst) {
Wonsik Kim6f23cfc2021-09-24 05:45:52 -0700237 *dst = new Codec2Buffer(
238 mFormat,
239 new ABuffer(mDataConverter->targetSize(srcBuffer->size())));
240 }
241 sp<MediaCodecBuffer> dstBuffer = *dst;
242 status_t err = mDataConverter->convert(srcBuffer, dstBuffer);
243 if (err != OK) {
244 ALOGD("[%s] buffer conversion failed: %d", mName, err);
245 return false;
246 }
247 dstBuffer->setFormat(mFormatWithConverter);
248 return true;
249}
250
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700251void OutputBuffers::clearStash() {
252 mPending.clear();
253 mReorderStash.clear();
254 mDepth = 0;
255 mKey = C2Config::ORDINAL;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700256}
257
258void OutputBuffers::flushStash() {
259 for (StashEntry& e : mPending) {
260 e.notify = false;
261 }
262 for (StashEntry& e : mReorderStash) {
263 e.notify = false;
264 }
265}
266
267uint32_t OutputBuffers::getReorderDepth() const {
268 return mDepth;
269}
270
271void OutputBuffers::setReorderDepth(uint32_t depth) {
272 mPending.splice(mPending.end(), mReorderStash);
273 mDepth = depth;
274}
275
276void OutputBuffers::setReorderKey(C2Config::ordinal_key_t key) {
277 mPending.splice(mPending.end(), mReorderStash);
278 mKey = key;
279}
280
281void OutputBuffers::pushToStash(
282 const std::shared_ptr<C2Buffer>& buffer,
283 bool notify,
284 int64_t timestamp,
285 int32_t flags,
286 const sp<AMessage>& format,
287 const C2WorkOrdinalStruct& ordinal) {
288 bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;
289 if (!buffer && eos) {
290 // TRICKY: we may be violating ordering of the stash here. Because we
291 // don't expect any more emplace() calls after this, the ordering should
292 // not matter.
293 mReorderStash.emplace_back(
294 buffer, notify, timestamp, flags, format, ordinal);
295 } else {
296 flags = flags & ~MediaCodec::BUFFER_FLAG_EOS;
297 auto it = mReorderStash.begin();
298 for (; it != mReorderStash.end(); ++it) {
299 if (less(ordinal, it->ordinal)) {
300 break;
301 }
302 }
303 mReorderStash.emplace(it,
304 buffer, notify, timestamp, flags, format, ordinal);
305 if (eos) {
306 mReorderStash.back().flags =
307 mReorderStash.back().flags | MediaCodec::BUFFER_FLAG_EOS;
308 }
309 }
310 while (!mReorderStash.empty() && mReorderStash.size() > mDepth) {
311 mPending.push_back(mReorderStash.front());
312 mReorderStash.pop_front();
313 }
314 ALOGV("[%s] %s: pushToStash -- pending size = %zu", mName, __func__, mPending.size());
315}
316
317OutputBuffers::BufferAction OutputBuffers::popFromStashAndRegister(
318 std::shared_ptr<C2Buffer>* c2Buffer,
319 size_t* index,
320 sp<MediaCodecBuffer>* outBuffer) {
321 if (mPending.empty()) {
322 return SKIP;
323 }
324
325 // Retrieve the first entry.
326 StashEntry &entry = mPending.front();
327
328 *c2Buffer = entry.buffer;
329 sp<AMessage> outputFormat = entry.format;
330
Wonsik Kim970bf0b2020-11-10 11:54:15 -0800331 if (entry.notify && mFormat != outputFormat) {
332 updateSkipCutBuffer(outputFormat);
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800333 // Trigger image data processing to the new format
334 mLastImageData.clear();
Wonsik Kim970bf0b2020-11-10 11:54:15 -0800335 ALOGV("[%s] popFromStashAndRegister: output format reference changed: %p -> %p",
336 mName, mFormat.get(), outputFormat.get());
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800337 ALOGD("[%s] popFromStashAndRegister: at %lldus, output format changed to %s",
338 mName, (long long)entry.timestamp, outputFormat->debugString().c_str());
Wonsik Kim970bf0b2020-11-10 11:54:15 -0800339 setFormat(outputFormat);
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700340 }
341
342 // Flushing mReorderStash because no other buffers should come after output
343 // EOS.
344 if (entry.flags & MediaCodec::BUFFER_FLAG_EOS) {
345 // Flush reorder stash
346 setReorderDepth(0);
347 }
348
349 if (!entry.notify) {
350 mPending.pop_front();
351 return DISCARD;
352 }
353
354 // Try to register the buffer.
355 status_t err = registerBuffer(*c2Buffer, index, outBuffer);
356 if (err != OK) {
357 if (err != WOULD_BLOCK) {
358 return REALLOCATE;
359 }
360 return RETRY;
361 }
362
363 // Append information from the front stash entry to outBuffer.
364 (*outBuffer)->meta()->setInt64("timeUs", entry.timestamp);
365 (*outBuffer)->meta()->setInt32("flags", entry.flags);
Byeongjo Park25c3a3d2020-06-12 17:24:21 +0900366 (*outBuffer)->meta()->setInt64("frameIndex", entry.ordinal.frameIndex.peekll());
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700367 ALOGV("[%s] popFromStashAndRegister: "
368 "out buffer index = %zu [%p] => %p + %zu (%lld)",
369 mName, *index, outBuffer->get(),
370 (*outBuffer)->data(), (*outBuffer)->size(),
371 (long long)entry.timestamp);
372
373 // The front entry of mPending will be removed now that the registration
374 // succeeded.
375 mPending.pop_front();
376 return NOTIFY_CLIENT;
377}
378
379bool OutputBuffers::popPending(StashEntry *entry) {
380 if (mPending.empty()) {
381 return false;
382 }
383 *entry = mPending.front();
384 mPending.pop_front();
385 return true;
386}
387
388void OutputBuffers::deferPending(const OutputBuffers::StashEntry &entry) {
389 mPending.push_front(entry);
390}
391
392bool OutputBuffers::hasPending() const {
393 return !mPending.empty();
394}
395
396bool OutputBuffers::less(
397 const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2) const {
398 switch (mKey) {
399 case C2Config::ORDINAL: return o1.frameIndex < o2.frameIndex;
400 case C2Config::TIMESTAMP: return o1.timestamp < o2.timestamp;
401 case C2Config::CUSTOM: return o1.customOrdinal < o2.customOrdinal;
402 default:
403 ALOGD("Unrecognized key; default to timestamp");
404 return o1.frameIndex < o2.frameIndex;
405 }
406}
407
Wonsik Kim469c8342019-04-11 16:46:09 -0700408// LocalBufferPool
409
Wonsik Kim41d83432020-04-27 16:40:49 -0700410constexpr size_t kInitialPoolCapacity = kMaxLinearBufferSize;
411constexpr size_t kMaxPoolCapacity = kMaxLinearBufferSize * 32;
412
413std::shared_ptr<LocalBufferPool> LocalBufferPool::Create() {
414 return std::shared_ptr<LocalBufferPool>(new LocalBufferPool(kInitialPoolCapacity));
Wonsik Kim469c8342019-04-11 16:46:09 -0700415}
416
417sp<ABuffer> LocalBufferPool::newBuffer(size_t capacity) {
418 Mutex::Autolock lock(mMutex);
419 auto it = std::find_if(
420 mPool.begin(), mPool.end(),
421 [capacity](const std::vector<uint8_t> &vec) {
422 return vec.capacity() >= capacity;
423 });
424 if (it != mPool.end()) {
425 sp<ABuffer> buffer = new VectorBuffer(std::move(*it), shared_from_this());
426 mPool.erase(it);
427 return buffer;
428 }
429 if (mUsedSize + capacity > mPoolCapacity) {
430 while (!mPool.empty()) {
431 mUsedSize -= mPool.back().capacity();
432 mPool.pop_back();
433 }
Wonsik Kim41d83432020-04-27 16:40:49 -0700434 while (mUsedSize + capacity > mPoolCapacity && mPoolCapacity * 2 <= kMaxPoolCapacity) {
435 ALOGD("Increasing local buffer pool capacity from %zu to %zu",
436 mPoolCapacity, mPoolCapacity * 2);
437 mPoolCapacity *= 2;
438 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700439 if (mUsedSize + capacity > mPoolCapacity) {
440 ALOGD("mUsedSize = %zu, capacity = %zu, mPoolCapacity = %zu",
441 mUsedSize, capacity, mPoolCapacity);
442 return nullptr;
443 }
444 }
445 std::vector<uint8_t> vec(capacity);
446 mUsedSize += vec.capacity();
447 return new VectorBuffer(std::move(vec), shared_from_this());
448}
449
450LocalBufferPool::VectorBuffer::VectorBuffer(
451 std::vector<uint8_t> &&vec, const std::shared_ptr<LocalBufferPool> &pool)
452 : ABuffer(vec.data(), vec.capacity()),
453 mVec(std::move(vec)),
454 mPool(pool) {
455}
456
457LocalBufferPool::VectorBuffer::~VectorBuffer() {
458 std::shared_ptr<LocalBufferPool> pool = mPool.lock();
459 if (pool) {
460 // If pool is alive, return the vector back to the pool so that
461 // it can be recycled.
462 pool->returnVector(std::move(mVec));
463 }
464}
465
466void LocalBufferPool::returnVector(std::vector<uint8_t> &&vec) {
467 Mutex::Autolock lock(mMutex);
468 mPool.push_front(std::move(vec));
469}
470
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700471// FlexBuffersImpl
472
Wonsik Kim469c8342019-04-11 16:46:09 -0700473size_t FlexBuffersImpl::assignSlot(const sp<Codec2Buffer> &buffer) {
474 for (size_t i = 0; i < mBuffers.size(); ++i) {
475 if (mBuffers[i].clientBuffer == nullptr
476 && mBuffers[i].compBuffer.expired()) {
477 mBuffers[i].clientBuffer = buffer;
478 return i;
479 }
480 }
481 mBuffers.push_back({ buffer, std::weak_ptr<C2Buffer>() });
482 return mBuffers.size() - 1;
483}
484
Wonsik Kim469c8342019-04-11 16:46:09 -0700485bool FlexBuffersImpl::releaseSlot(
486 const sp<MediaCodecBuffer> &buffer,
487 std::shared_ptr<C2Buffer> *c2buffer,
488 bool release) {
489 sp<Codec2Buffer> clientBuffer;
490 size_t index = mBuffers.size();
491 for (size_t i = 0; i < mBuffers.size(); ++i) {
492 if (mBuffers[i].clientBuffer == buffer) {
493 clientBuffer = mBuffers[i].clientBuffer;
494 if (release) {
495 mBuffers[i].clientBuffer.clear();
496 }
497 index = i;
498 break;
499 }
500 }
501 if (clientBuffer == nullptr) {
502 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
503 return false;
504 }
505 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
506 if (!result) {
507 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700508 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700509 mBuffers[index].compBuffer = result;
510 }
511 if (c2buffer) {
512 *c2buffer = result;
513 }
514 return true;
515}
516
517bool FlexBuffersImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
518 for (size_t i = 0; i < mBuffers.size(); ++i) {
519 std::shared_ptr<C2Buffer> compBuffer =
520 mBuffers[i].compBuffer.lock();
521 if (!compBuffer || compBuffer != c2buffer) {
522 continue;
523 }
524 mBuffers[i].compBuffer.reset();
525 ALOGV("[%s] codec released buffer #%zu", mName, i);
526 return true;
527 }
528 ALOGV("[%s] codec released an unknown buffer", mName);
529 return false;
530}
531
532void FlexBuffersImpl::flush() {
533 ALOGV("[%s] buffers are flushed %zu", mName, mBuffers.size());
534 mBuffers.clear();
535}
536
Wonsik Kim0487b782020-10-28 11:45:50 -0700537size_t FlexBuffersImpl::numActiveSlots() const {
Wonsik Kim469c8342019-04-11 16:46:09 -0700538 return std::count_if(
539 mBuffers.begin(), mBuffers.end(),
540 [](const Entry &entry) {
Wonsik Kim0487b782020-10-28 11:45:50 -0700541 return (entry.clientBuffer != nullptr
542 || !entry.compBuffer.expired());
Wonsik Kim469c8342019-04-11 16:46:09 -0700543 });
544}
545
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700546size_t FlexBuffersImpl::numComponentBuffers() const {
547 return std::count_if(
548 mBuffers.begin(), mBuffers.end(),
549 [](const Entry &entry) {
550 return !entry.compBuffer.expired();
551 });
552}
553
Wonsik Kim469c8342019-04-11 16:46:09 -0700554// BuffersArrayImpl
555
556void BuffersArrayImpl::initialize(
557 const FlexBuffersImpl &impl,
558 size_t minSize,
559 std::function<sp<Codec2Buffer>()> allocate) {
560 mImplName = impl.mImplName + "[N]";
561 mName = mImplName.c_str();
562 for (size_t i = 0; i < impl.mBuffers.size(); ++i) {
563 sp<Codec2Buffer> clientBuffer = impl.mBuffers[i].clientBuffer;
564 bool ownedByClient = (clientBuffer != nullptr);
565 if (!ownedByClient) {
566 clientBuffer = allocate();
567 }
568 mBuffers.push_back({ clientBuffer, impl.mBuffers[i].compBuffer, ownedByClient });
569 }
570 ALOGV("[%s] converted %zu buffers to array mode of %zu", mName, mBuffers.size(), minSize);
571 for (size_t i = impl.mBuffers.size(); i < minSize; ++i) {
572 mBuffers.push_back({ allocate(), std::weak_ptr<C2Buffer>(), false });
573 }
574}
575
576status_t BuffersArrayImpl::grabBuffer(
577 size_t *index,
578 sp<Codec2Buffer> *buffer,
579 std::function<bool(const sp<Codec2Buffer> &)> match) {
580 // allBuffersDontMatch remains true if all buffers are available but
581 // match() returns false for every buffer.
582 bool allBuffersDontMatch = true;
583 for (size_t i = 0; i < mBuffers.size(); ++i) {
584 if (!mBuffers[i].ownedByClient && mBuffers[i].compBuffer.expired()) {
585 if (match(mBuffers[i].clientBuffer)) {
586 mBuffers[i].ownedByClient = true;
587 *buffer = mBuffers[i].clientBuffer;
588 (*buffer)->meta()->clear();
589 (*buffer)->setRange(0, (*buffer)->capacity());
590 *index = i;
591 return OK;
592 }
593 } else {
594 allBuffersDontMatch = false;
595 }
596 }
597 return allBuffersDontMatch ? NO_MEMORY : WOULD_BLOCK;
598}
599
600bool BuffersArrayImpl::returnBuffer(
601 const sp<MediaCodecBuffer> &buffer,
602 std::shared_ptr<C2Buffer> *c2buffer,
603 bool release) {
604 sp<Codec2Buffer> clientBuffer;
605 size_t index = mBuffers.size();
606 for (size_t i = 0; i < mBuffers.size(); ++i) {
607 if (mBuffers[i].clientBuffer == buffer) {
608 if (!mBuffers[i].ownedByClient) {
609 ALOGD("[%s] Client returned a buffer it does not own according to our record: %zu",
610 mName, i);
611 }
612 clientBuffer = mBuffers[i].clientBuffer;
613 if (release) {
614 mBuffers[i].ownedByClient = false;
615 }
616 index = i;
617 break;
618 }
619 }
620 if (clientBuffer == nullptr) {
621 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
622 return false;
623 }
624 ALOGV("[%s] %s: matching buffer found (index=%zu)", mName, __func__, index);
625 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
626 if (!result) {
627 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700628 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700629 mBuffers[index].compBuffer = result;
630 }
631 if (c2buffer) {
632 *c2buffer = result;
633 }
634 return true;
635}
636
637bool BuffersArrayImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
638 for (size_t i = 0; i < mBuffers.size(); ++i) {
639 std::shared_ptr<C2Buffer> compBuffer =
640 mBuffers[i].compBuffer.lock();
641 if (!compBuffer) {
642 continue;
643 }
644 if (c2buffer == compBuffer) {
645 if (mBuffers[i].ownedByClient) {
646 // This should not happen.
647 ALOGD("[%s] codec released a buffer owned by client "
648 "(index %zu)", mName, i);
649 }
650 mBuffers[i].compBuffer.reset();
651 ALOGV("[%s] codec released buffer #%zu(array mode)", mName, i);
652 return true;
653 }
654 }
655 ALOGV("[%s] codec released an unknown buffer (array mode)", mName);
656 return false;
657}
658
659void BuffersArrayImpl::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
660 array->clear();
661 for (const Entry &entry : mBuffers) {
662 array->push(entry.clientBuffer);
663 }
664}
665
666void BuffersArrayImpl::flush() {
667 for (Entry &entry : mBuffers) {
668 entry.ownedByClient = false;
669 }
670}
671
672void BuffersArrayImpl::realloc(std::function<sp<Codec2Buffer>()> alloc) {
673 size_t size = mBuffers.size();
674 mBuffers.clear();
675 for (size_t i = 0; i < size; ++i) {
676 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
677 }
678}
679
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700680void BuffersArrayImpl::grow(
681 size_t newSize, std::function<sp<Codec2Buffer>()> alloc) {
682 CHECK_LT(mBuffers.size(), newSize);
683 while (mBuffers.size() < newSize) {
684 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
685 }
686}
687
Wonsik Kim0487b782020-10-28 11:45:50 -0700688size_t BuffersArrayImpl::numActiveSlots() const {
Wonsik Kim469c8342019-04-11 16:46:09 -0700689 return std::count_if(
690 mBuffers.begin(), mBuffers.end(),
691 [](const Entry &entry) {
Wonsik Kim0487b782020-10-28 11:45:50 -0700692 return entry.ownedByClient || !entry.compBuffer.expired();
Wonsik Kim469c8342019-04-11 16:46:09 -0700693 });
694}
695
Wonsik Kima39882b2019-06-20 16:13:56 -0700696size_t BuffersArrayImpl::arraySize() const {
697 return mBuffers.size();
698}
699
Wonsik Kim469c8342019-04-11 16:46:09 -0700700// InputBuffersArray
701
702void InputBuffersArray::initialize(
703 const FlexBuffersImpl &impl,
704 size_t minSize,
705 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700706 mAllocate = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -0700707 mImpl.initialize(impl, minSize, allocate);
708}
709
710void InputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
711 mImpl.getArray(array);
712}
713
714bool InputBuffersArray::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
715 sp<Codec2Buffer> c2Buffer;
716 status_t err = mImpl.grabBuffer(index, &c2Buffer);
717 if (err == OK) {
718 c2Buffer->setFormat(mFormat);
719 handleImageData(c2Buffer);
720 *buffer = c2Buffer;
721 return true;
722 }
723 return false;
724}
725
726bool InputBuffersArray::releaseBuffer(
727 const sp<MediaCodecBuffer> &buffer,
728 std::shared_ptr<C2Buffer> *c2buffer,
729 bool release) {
730 return mImpl.returnBuffer(buffer, c2buffer, release);
731}
732
733bool InputBuffersArray::expireComponentBuffer(
734 const std::shared_ptr<C2Buffer> &c2buffer) {
735 return mImpl.expireComponentBuffer(c2buffer);
736}
737
738void InputBuffersArray::flush() {
739 mImpl.flush();
740}
741
Wonsik Kim0487b782020-10-28 11:45:50 -0700742size_t InputBuffersArray::numActiveSlots() const {
743 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700744}
745
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700746sp<Codec2Buffer> InputBuffersArray::createNewBuffer() {
747 return mAllocate();
748}
749
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800750// SlotInputBuffers
751
752bool SlotInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
753 sp<Codec2Buffer> newBuffer = createNewBuffer();
754 *index = mImpl.assignSlot(newBuffer);
755 *buffer = newBuffer;
756 return true;
757}
758
759bool SlotInputBuffers::releaseBuffer(
760 const sp<MediaCodecBuffer> &buffer,
761 std::shared_ptr<C2Buffer> *c2buffer,
762 bool release) {
763 return mImpl.releaseSlot(buffer, c2buffer, release);
764}
765
766bool SlotInputBuffers::expireComponentBuffer(
767 const std::shared_ptr<C2Buffer> &c2buffer) {
768 return mImpl.expireComponentBuffer(c2buffer);
769}
770
771void SlotInputBuffers::flush() {
772 mImpl.flush();
773}
774
775std::unique_ptr<InputBuffers> SlotInputBuffers::toArrayMode(size_t) {
776 TRESPASS("Array mode should not be called at non-legacy mode");
777 return nullptr;
778}
779
Wonsik Kim0487b782020-10-28 11:45:50 -0700780size_t SlotInputBuffers::numActiveSlots() const {
781 return mImpl.numActiveSlots();
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800782}
783
784sp<Codec2Buffer> SlotInputBuffers::createNewBuffer() {
785 return new DummyContainerBuffer{mFormat, nullptr};
786}
787
Wonsik Kim469c8342019-04-11 16:46:09 -0700788// LinearInputBuffers
789
790bool LinearInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700791 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700792 if (newBuffer == nullptr) {
793 return false;
794 }
795 *index = mImpl.assignSlot(newBuffer);
796 *buffer = newBuffer;
797 return true;
798}
799
800bool LinearInputBuffers::releaseBuffer(
801 const sp<MediaCodecBuffer> &buffer,
802 std::shared_ptr<C2Buffer> *c2buffer,
803 bool release) {
804 return mImpl.releaseSlot(buffer, c2buffer, release);
805}
806
807bool LinearInputBuffers::expireComponentBuffer(
808 const std::shared_ptr<C2Buffer> &c2buffer) {
809 return mImpl.expireComponentBuffer(c2buffer);
810}
811
812void LinearInputBuffers::flush() {
813 // This is no-op by default unless we're in array mode where we need to keep
814 // track of the flushed work.
815 mImpl.flush();
816}
817
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700818std::unique_ptr<InputBuffers> LinearInputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700819 std::unique_ptr<InputBuffersArray> array(
820 new InputBuffersArray(mComponentName.c_str(), "1D-Input[N]"));
821 array->setPool(mPool);
822 array->setFormat(mFormat);
823 array->initialize(
824 mImpl,
825 size,
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700826 [pool = mPool, format = mFormat] () -> sp<Codec2Buffer> {
827 return Alloc(pool, format);
828 });
Wonsik Kim469c8342019-04-11 16:46:09 -0700829 return std::move(array);
830}
831
Wonsik Kim0487b782020-10-28 11:45:50 -0700832size_t LinearInputBuffers::numActiveSlots() const {
833 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700834}
835
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700836// static
837sp<Codec2Buffer> LinearInputBuffers::Alloc(
838 const std::shared_ptr<C2BlockPool> &pool, const sp<AMessage> &format) {
839 int32_t capacity = kLinearBufferSize;
840 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
841 if ((size_t)capacity > kMaxLinearBufferSize) {
842 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
843 capacity = kMaxLinearBufferSize;
844 }
845
Wonsik Kim666604a2020-05-14 16:57:49 -0700846 int64_t usageValue = 0;
847 (void)format->findInt64("android._C2MemoryUsage", &usageValue);
848 C2MemoryUsage usage{usageValue | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE};
Wonsik Kim469c8342019-04-11 16:46:09 -0700849 std::shared_ptr<C2LinearBlock> block;
850
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700851 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700852 if (err != C2_OK) {
853 return nullptr;
854 }
855
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700856 return LinearBlockBuffer::Allocate(format, block);
857}
858
859sp<Codec2Buffer> LinearInputBuffers::createNewBuffer() {
860 return Alloc(mPool, mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -0700861}
862
863// EncryptedLinearInputBuffers
864
865EncryptedLinearInputBuffers::EncryptedLinearInputBuffers(
866 bool secure,
867 const sp<MemoryDealer> &dealer,
868 const sp<ICrypto> &crypto,
869 int32_t heapSeqNum,
870 size_t capacity,
871 size_t numInputSlots,
872 const char *componentName, const char *name)
873 : LinearInputBuffers(componentName, name),
874 mUsage({0, 0}),
875 mDealer(dealer),
876 mCrypto(crypto),
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700877 mMemoryVector(new std::vector<Entry>){
Wonsik Kim469c8342019-04-11 16:46:09 -0700878 if (secure) {
879 mUsage = { C2MemoryUsage::READ_PROTECTED, 0 };
880 } else {
881 mUsage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
882 }
883 for (size_t i = 0; i < numInputSlots; ++i) {
884 sp<IMemory> memory = mDealer->allocate(capacity);
885 if (memory == nullptr) {
886 ALOGD("[%s] Failed to allocate memory from dealer: only %zu slots allocated",
887 mName, i);
888 break;
889 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700890 mMemoryVector->push_back({std::weak_ptr<C2LinearBlock>(), memory, heapSeqNum});
Wonsik Kim469c8342019-04-11 16:46:09 -0700891 }
892}
893
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700894std::unique_ptr<InputBuffers> EncryptedLinearInputBuffers::toArrayMode(size_t size) {
895 std::unique_ptr<InputBuffersArray> array(
896 new InputBuffersArray(mComponentName.c_str(), "1D-EncryptedInput[N]"));
897 array->setPool(mPool);
898 array->setFormat(mFormat);
899 array->initialize(
900 mImpl,
901 size,
902 [pool = mPool,
903 format = mFormat,
904 usage = mUsage,
905 memoryVector = mMemoryVector] () -> sp<Codec2Buffer> {
906 return Alloc(pool, format, usage, memoryVector);
907 });
908 return std::move(array);
909}
910
911
912// static
913sp<Codec2Buffer> EncryptedLinearInputBuffers::Alloc(
914 const std::shared_ptr<C2BlockPool> &pool,
915 const sp<AMessage> &format,
916 C2MemoryUsage usage,
917 const std::shared_ptr<std::vector<EncryptedLinearInputBuffers::Entry>> &memoryVector) {
918 int32_t capacity = kLinearBufferSize;
919 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
920 if ((size_t)capacity > kMaxLinearBufferSize) {
921 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
922 capacity = kMaxLinearBufferSize;
923 }
924
Wonsik Kim469c8342019-04-11 16:46:09 -0700925 sp<IMemory> memory;
926 size_t slot = 0;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700927 int32_t heapSeqNum = -1;
928 for (; slot < memoryVector->size(); ++slot) {
929 if (memoryVector->at(slot).block.expired()) {
930 memory = memoryVector->at(slot).memory;
931 heapSeqNum = memoryVector->at(slot).heapSeqNum;
Wonsik Kim469c8342019-04-11 16:46:09 -0700932 break;
933 }
934 }
935 if (memory == nullptr) {
936 return nullptr;
937 }
938
939 std::shared_ptr<C2LinearBlock> block;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700940 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700941 if (err != C2_OK || block == nullptr) {
942 return nullptr;
943 }
944
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700945 memoryVector->at(slot).block = block;
946 return new EncryptedLinearBlockBuffer(format, block, memory, heapSeqNum);
947}
948
949sp<Codec2Buffer> EncryptedLinearInputBuffers::createNewBuffer() {
950 // TODO: android_2020
951 return nullptr;
Wonsik Kim469c8342019-04-11 16:46:09 -0700952}
953
954// GraphicMetadataInputBuffers
955
956GraphicMetadataInputBuffers::GraphicMetadataInputBuffers(
957 const char *componentName, const char *name)
958 : InputBuffers(componentName, name),
959 mImpl(mName),
960 mStore(GetCodec2PlatformAllocatorStore()) { }
961
962bool GraphicMetadataInputBuffers::requestNewBuffer(
963 size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700964 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700965 if (newBuffer == nullptr) {
966 return false;
967 }
968 *index = mImpl.assignSlot(newBuffer);
969 *buffer = newBuffer;
970 return true;
971}
972
973bool GraphicMetadataInputBuffers::releaseBuffer(
974 const sp<MediaCodecBuffer> &buffer,
975 std::shared_ptr<C2Buffer> *c2buffer,
976 bool release) {
977 return mImpl.releaseSlot(buffer, c2buffer, release);
978}
979
980bool GraphicMetadataInputBuffers::expireComponentBuffer(
981 const std::shared_ptr<C2Buffer> &c2buffer) {
982 return mImpl.expireComponentBuffer(c2buffer);
983}
984
985void GraphicMetadataInputBuffers::flush() {
986 // This is no-op by default unless we're in array mode where we need to keep
987 // track of the flushed work.
988}
989
990std::unique_ptr<InputBuffers> GraphicMetadataInputBuffers::toArrayMode(
991 size_t size) {
992 std::shared_ptr<C2Allocator> alloc;
993 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
994 if (err != C2_OK) {
995 return nullptr;
996 }
997 std::unique_ptr<InputBuffersArray> array(
998 new InputBuffersArray(mComponentName.c_str(), "2D-MetaInput[N]"));
999 array->setPool(mPool);
1000 array->setFormat(mFormat);
1001 array->initialize(
1002 mImpl,
1003 size,
1004 [format = mFormat, alloc]() -> sp<Codec2Buffer> {
1005 return new GraphicMetadataBuffer(format, alloc);
1006 });
1007 return std::move(array);
1008}
1009
Wonsik Kim0487b782020-10-28 11:45:50 -07001010size_t GraphicMetadataInputBuffers::numActiveSlots() const {
1011 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001012}
1013
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001014sp<Codec2Buffer> GraphicMetadataInputBuffers::createNewBuffer() {
1015 std::shared_ptr<C2Allocator> alloc;
1016 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
1017 if (err != C2_OK) {
1018 return nullptr;
1019 }
1020 return new GraphicMetadataBuffer(mFormat, alloc);
1021}
1022
Wonsik Kim469c8342019-04-11 16:46:09 -07001023// GraphicInputBuffers
1024
1025GraphicInputBuffers::GraphicInputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -07001026 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -07001027 : InputBuffers(componentName, name),
1028 mImpl(mName),
Wonsik Kim41d83432020-04-27 16:40:49 -07001029 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -07001030
1031bool GraphicInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001032 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -07001033 if (newBuffer == nullptr) {
1034 return false;
1035 }
1036 *index = mImpl.assignSlot(newBuffer);
1037 handleImageData(newBuffer);
1038 *buffer = newBuffer;
1039 return true;
1040}
1041
1042bool GraphicInputBuffers::releaseBuffer(
1043 const sp<MediaCodecBuffer> &buffer,
1044 std::shared_ptr<C2Buffer> *c2buffer,
1045 bool release) {
1046 return mImpl.releaseSlot(buffer, c2buffer, release);
1047}
1048
1049bool GraphicInputBuffers::expireComponentBuffer(
1050 const std::shared_ptr<C2Buffer> &c2buffer) {
1051 return mImpl.expireComponentBuffer(c2buffer);
1052}
1053
1054void GraphicInputBuffers::flush() {
1055 // This is no-op by default unless we're in array mode where we need to keep
1056 // track of the flushed work.
1057}
1058
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001059static uint32_t extractPixelFormat(const sp<AMessage> &format) {
1060 int32_t frameworkColorFormat = 0;
1061 if (!format->findInt32("android._color-format", &frameworkColorFormat)) {
1062 return PIXEL_FORMAT_UNKNOWN;
1063 }
1064 uint32_t pixelFormat = PIXEL_FORMAT_UNKNOWN;
1065 if (C2Mapper::mapPixelFormatFrameworkToCodec(frameworkColorFormat, &pixelFormat)) {
1066 return pixelFormat;
1067 }
1068 return PIXEL_FORMAT_UNKNOWN;
1069}
1070
Wonsik Kim469c8342019-04-11 16:46:09 -07001071std::unique_ptr<InputBuffers> GraphicInputBuffers::toArrayMode(size_t size) {
1072 std::unique_ptr<InputBuffersArray> array(
1073 new InputBuffersArray(mComponentName.c_str(), "2D-BB-Input[N]"));
1074 array->setPool(mPool);
1075 array->setFormat(mFormat);
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001076 uint32_t pixelFormat = extractPixelFormat(mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -07001077 array->initialize(
1078 mImpl,
1079 size,
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001080 [pool = mPool, format = mFormat, lbp = mLocalBufferPool, pixelFormat]()
1081 -> sp<Codec2Buffer> {
Wonsik Kim469c8342019-04-11 16:46:09 -07001082 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
1083 return AllocateGraphicBuffer(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001084 pool, format, pixelFormat, usage, lbp);
Wonsik Kim469c8342019-04-11 16:46:09 -07001085 });
1086 return std::move(array);
1087}
1088
Wonsik Kim0487b782020-10-28 11:45:50 -07001089size_t GraphicInputBuffers::numActiveSlots() const {
1090 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001091}
1092
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001093sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
Wonsik Kim666604a2020-05-14 16:57:49 -07001094 int64_t usageValue = 0;
1095 (void)mFormat->findInt64("android._C2MemoryUsage", &usageValue);
1096 C2MemoryUsage usage{usageValue | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE};
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001097 return AllocateGraphicBuffer(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001098 mPool, mFormat, extractPixelFormat(mFormat), usage, mLocalBufferPool);
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001099}
1100
Wonsik Kim469c8342019-04-11 16:46:09 -07001101// OutputBuffersArray
1102
1103void OutputBuffersArray::initialize(
1104 const FlexBuffersImpl &impl,
1105 size_t minSize,
1106 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001107 mAlloc = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -07001108 mImpl.initialize(impl, minSize, allocate);
1109}
1110
1111status_t OutputBuffersArray::registerBuffer(
1112 const std::shared_ptr<C2Buffer> &buffer,
1113 size_t *index,
1114 sp<MediaCodecBuffer> *clientBuffer) {
1115 sp<Codec2Buffer> c2Buffer;
1116 status_t err = mImpl.grabBuffer(
1117 index,
1118 &c2Buffer,
1119 [buffer](const sp<Codec2Buffer> &clientBuffer) {
1120 return clientBuffer->canCopy(buffer);
1121 });
1122 if (err == WOULD_BLOCK) {
1123 ALOGV("[%s] buffers temporarily not available", mName);
1124 return err;
1125 } else if (err != OK) {
1126 ALOGD("[%s] grabBuffer failed: %d", mName, err);
1127 return err;
1128 }
1129 c2Buffer->setFormat(mFormat);
Wonsik Kim6f23cfc2021-09-24 05:45:52 -07001130 if (!convert(buffer, &c2Buffer) && !c2Buffer->copy(buffer)) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001131 ALOGD("[%s] copy buffer failed", mName);
1132 return WOULD_BLOCK;
1133 }
1134 submit(c2Buffer);
1135 handleImageData(c2Buffer);
1136 *clientBuffer = c2Buffer;
1137 ALOGV("[%s] grabbed buffer %zu", mName, *index);
1138 return OK;
1139}
1140
1141status_t OutputBuffersArray::registerCsd(
1142 const C2StreamInitDataInfo::output *csd,
1143 size_t *index,
1144 sp<MediaCodecBuffer> *clientBuffer) {
1145 sp<Codec2Buffer> c2Buffer;
1146 status_t err = mImpl.grabBuffer(
1147 index,
1148 &c2Buffer,
1149 [csd](const sp<Codec2Buffer> &clientBuffer) {
1150 return clientBuffer->base() != nullptr
1151 && clientBuffer->capacity() >= csd->flexCount();
1152 });
1153 if (err != OK) {
1154 return err;
1155 }
1156 memcpy(c2Buffer->base(), csd->m.value, csd->flexCount());
1157 c2Buffer->setRange(0, csd->flexCount());
1158 c2Buffer->setFormat(mFormat);
1159 *clientBuffer = c2Buffer;
1160 return OK;
1161}
1162
1163bool OutputBuffersArray::releaseBuffer(
1164 const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) {
1165 return mImpl.returnBuffer(buffer, c2buffer, true);
1166}
1167
1168void OutputBuffersArray::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1169 (void)flushedWork;
1170 mImpl.flush();
1171 if (mSkipCutBuffer != nullptr) {
1172 mSkipCutBuffer->clear();
1173 }
1174}
1175
1176void OutputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
1177 mImpl.getArray(array);
1178}
1179
Wonsik Kim0487b782020-10-28 11:45:50 -07001180size_t OutputBuffersArray::numActiveSlots() const {
1181 return mImpl.numActiveSlots();
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001182}
1183
Wonsik Kim469c8342019-04-11 16:46:09 -07001184void OutputBuffersArray::realloc(const std::shared_ptr<C2Buffer> &c2buffer) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001185 switch (c2buffer->data().type()) {
1186 case C2BufferData::LINEAR: {
1187 uint32_t size = kLinearBufferSize;
Nick Desaulniersd09eaea2019-10-07 20:19:39 -07001188 const std::vector<C2ConstLinearBlock> &linear_blocks = c2buffer->data().linearBlocks();
1189 const uint32_t block_size = linear_blocks.front().size();
1190 if (block_size < kMaxLinearBufferSize / 2) {
1191 size = block_size * 2;
Wonsik Kim469c8342019-04-11 16:46:09 -07001192 } else {
1193 size = kMaxLinearBufferSize;
1194 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001195 mAlloc = [format = mFormat, size] {
Wonsik Kim469c8342019-04-11 16:46:09 -07001196 return new LocalLinearBuffer(format, new ABuffer(size));
1197 };
Wonsik Kima39882b2019-06-20 16:13:56 -07001198 ALOGD("[%s] reallocating with linear buffer of size %u", mName, size);
Wonsik Kim469c8342019-04-11 16:46:09 -07001199 break;
1200 }
1201
Wonsik Kima39882b2019-06-20 16:13:56 -07001202 case C2BufferData::GRAPHIC: {
1203 // This is only called for RawGraphicOutputBuffers.
1204 mAlloc = [format = mFormat,
Wonsik Kim41d83432020-04-27 16:40:49 -07001205 lbp = LocalBufferPool::Create()] {
Wonsik Kima39882b2019-06-20 16:13:56 -07001206 return ConstGraphicBlockBuffer::AllocateEmpty(
1207 format,
1208 [lbp](size_t capacity) {
1209 return lbp->newBuffer(capacity);
1210 });
1211 };
1212 ALOGD("[%s] reallocating with graphic buffer: format = %s",
1213 mName, mFormat->debugString().c_str());
1214 break;
1215 }
Wonsik Kim469c8342019-04-11 16:46:09 -07001216
1217 case C2BufferData::INVALID: [[fallthrough]];
1218 case C2BufferData::LINEAR_CHUNKS: [[fallthrough]];
1219 case C2BufferData::GRAPHIC_CHUNKS: [[fallthrough]];
1220 default:
1221 ALOGD("Unsupported type: %d", (int)c2buffer->data().type());
1222 return;
1223 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001224 mImpl.realloc(mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -07001225}
1226
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001227void OutputBuffersArray::grow(size_t newSize) {
1228 mImpl.grow(newSize, mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -07001229}
1230
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001231void OutputBuffersArray::transferFrom(OutputBuffers* source) {
1232 mFormat = source->mFormat;
1233 mSkipCutBuffer = source->mSkipCutBuffer;
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001234 mPending = std::move(source->mPending);
1235 mReorderStash = std::move(source->mReorderStash);
1236 mDepth = source->mDepth;
1237 mKey = source->mKey;
1238}
1239
Wonsik Kim469c8342019-04-11 16:46:09 -07001240// FlexOutputBuffers
1241
1242status_t FlexOutputBuffers::registerBuffer(
1243 const std::shared_ptr<C2Buffer> &buffer,
1244 size_t *index,
1245 sp<MediaCodecBuffer> *clientBuffer) {
Wonsik Kim6f23cfc2021-09-24 05:45:52 -07001246 sp<Codec2Buffer> newBuffer;
1247 if (!convert(buffer, &newBuffer)) {
1248 newBuffer = wrap(buffer);
1249 if (newBuffer == nullptr) {
1250 return NO_MEMORY;
1251 }
Wonsik Kim469c8342019-04-11 16:46:09 -07001252 }
1253 newBuffer->setFormat(mFormat);
1254 *index = mImpl.assignSlot(newBuffer);
1255 handleImageData(newBuffer);
1256 *clientBuffer = newBuffer;
1257 ALOGV("[%s] registered buffer %zu", mName, *index);
1258 return OK;
1259}
1260
1261status_t FlexOutputBuffers::registerCsd(
1262 const C2StreamInitDataInfo::output *csd,
1263 size_t *index,
1264 sp<MediaCodecBuffer> *clientBuffer) {
1265 sp<Codec2Buffer> newBuffer = new LocalLinearBuffer(
1266 mFormat, ABuffer::CreateAsCopy(csd->m.value, csd->flexCount()));
1267 *index = mImpl.assignSlot(newBuffer);
1268 *clientBuffer = newBuffer;
1269 return OK;
1270}
1271
1272bool FlexOutputBuffers::releaseBuffer(
1273 const sp<MediaCodecBuffer> &buffer,
1274 std::shared_ptr<C2Buffer> *c2buffer) {
1275 return mImpl.releaseSlot(buffer, c2buffer, true);
1276}
1277
1278void FlexOutputBuffers::flush(
1279 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1280 (void) flushedWork;
1281 // This is no-op by default unless we're in array mode where we need to keep
1282 // track of the flushed work.
1283}
1284
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001285std::unique_ptr<OutputBuffersArray> FlexOutputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001286 std::unique_ptr<OutputBuffersArray> array(new OutputBuffersArray(mComponentName.c_str()));
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001287 array->transferFrom(this);
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001288 std::function<sp<Codec2Buffer>()> alloc = getAlloc();
1289 array->initialize(mImpl, size, alloc);
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001290 return array;
Wonsik Kim469c8342019-04-11 16:46:09 -07001291}
1292
Wonsik Kim0487b782020-10-28 11:45:50 -07001293size_t FlexOutputBuffers::numActiveSlots() const {
1294 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001295}
1296
1297// LinearOutputBuffers
1298
1299void LinearOutputBuffers::flush(
1300 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1301 if (mSkipCutBuffer != nullptr) {
1302 mSkipCutBuffer->clear();
1303 }
1304 FlexOutputBuffers::flush(flushedWork);
1305}
1306
1307sp<Codec2Buffer> LinearOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1308 if (buffer == nullptr) {
1309 ALOGV("[%s] using a dummy buffer", mName);
1310 return new LocalLinearBuffer(mFormat, new ABuffer(0));
1311 }
1312 if (buffer->data().type() != C2BufferData::LINEAR) {
1313 ALOGV("[%s] non-linear buffer %d", mName, buffer->data().type());
1314 // We expect linear output buffers from the component.
1315 return nullptr;
1316 }
1317 if (buffer->data().linearBlocks().size() != 1u) {
1318 ALOGV("[%s] no linear buffers", mName);
1319 // We expect one and only one linear block from the component.
1320 return nullptr;
1321 }
1322 sp<Codec2Buffer> clientBuffer = ConstLinearBlockBuffer::Allocate(mFormat, buffer);
1323 if (clientBuffer == nullptr) {
1324 ALOGD("[%s] ConstLinearBlockBuffer::Allocate failed", mName);
1325 return nullptr;
1326 }
1327 submit(clientBuffer);
1328 return clientBuffer;
1329}
1330
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001331std::function<sp<Codec2Buffer>()> LinearOutputBuffers::getAlloc() {
1332 return [format = mFormat]{
1333 // TODO: proper max output size
1334 return new LocalLinearBuffer(format, new ABuffer(kLinearBufferSize));
1335 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001336}
1337
1338// GraphicOutputBuffers
1339
1340sp<Codec2Buffer> GraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1341 return new DummyContainerBuffer(mFormat, buffer);
1342}
1343
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001344std::function<sp<Codec2Buffer>()> GraphicOutputBuffers::getAlloc() {
1345 return [format = mFormat]{
1346 return new DummyContainerBuffer(format);
1347 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001348}
1349
1350// RawGraphicOutputBuffers
1351
1352RawGraphicOutputBuffers::RawGraphicOutputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -07001353 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -07001354 : FlexOutputBuffers(componentName, name),
Wonsik Kim41d83432020-04-27 16:40:49 -07001355 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -07001356
1357sp<Codec2Buffer> RawGraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1358 if (buffer == nullptr) {
Wonsik Kim6f116902021-07-14 08:58:07 -07001359 return new Codec2Buffer(mFormat, new ABuffer(nullptr, 0));
Wonsik Kim469c8342019-04-11 16:46:09 -07001360 } else {
1361 return ConstGraphicBlockBuffer::Allocate(
1362 mFormat,
1363 buffer,
1364 [lbp = mLocalBufferPool](size_t capacity) {
1365 return lbp->newBuffer(capacity);
1366 });
1367 }
1368}
1369
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001370std::function<sp<Codec2Buffer>()> RawGraphicOutputBuffers::getAlloc() {
1371 return [format = mFormat, lbp = mLocalBufferPool]{
1372 return ConstGraphicBlockBuffer::AllocateEmpty(
1373 format,
1374 [lbp](size_t capacity) {
1375 return lbp->newBuffer(capacity);
1376 });
1377 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001378}
1379
1380} // namespace android