blob: 0f4a8d82a3d848e79c0094810f0e86a62fb170e8 [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) {
Wonsik Kim360ba0a2022-05-23 15:38:21 -0700211 if (src && src->data().type() != C2BufferData::LINEAR) {
Wonsik Kim6f23cfc2021-09-24 05:45:52 -0700212 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 }
Wonsik Kim360ba0a2022-05-23 15:38:21 -0700240 sp<MediaCodecBuffer> srcBuffer;
241 if (src) {
242 srcBuffer = ConstLinearBlockBuffer::Allocate(mFormat, src);
243 } else {
244 srcBuffer = new MediaCodecBuffer(mFormat, new ABuffer(0));
245 }
Wonsik Kim6f23cfc2021-09-24 05:45:52 -0700246 if (!srcBuffer) {
247 return false;
248 }
Greg Kaiser92dc4542021-10-08 06:58:19 -0700249 if (!*dst) {
Wonsik Kim6f23cfc2021-09-24 05:45:52 -0700250 *dst = new Codec2Buffer(
251 mFormat,
252 new ABuffer(mDataConverter->targetSize(srcBuffer->size())));
253 }
254 sp<MediaCodecBuffer> dstBuffer = *dst;
255 status_t err = mDataConverter->convert(srcBuffer, dstBuffer);
256 if (err != OK) {
257 ALOGD("[%s] buffer conversion failed: %d", mName, err);
258 return false;
259 }
260 dstBuffer->setFormat(mFormatWithConverter);
261 return true;
262}
263
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700264void OutputBuffers::clearStash() {
265 mPending.clear();
266 mReorderStash.clear();
267 mDepth = 0;
268 mKey = C2Config::ORDINAL;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700269}
270
271void OutputBuffers::flushStash() {
272 for (StashEntry& e : mPending) {
273 e.notify = false;
274 }
275 for (StashEntry& e : mReorderStash) {
276 e.notify = false;
277 }
278}
279
280uint32_t OutputBuffers::getReorderDepth() const {
281 return mDepth;
282}
283
284void OutputBuffers::setReorderDepth(uint32_t depth) {
285 mPending.splice(mPending.end(), mReorderStash);
286 mDepth = depth;
287}
288
289void OutputBuffers::setReorderKey(C2Config::ordinal_key_t key) {
290 mPending.splice(mPending.end(), mReorderStash);
291 mKey = key;
292}
293
294void OutputBuffers::pushToStash(
295 const std::shared_ptr<C2Buffer>& buffer,
296 bool notify,
297 int64_t timestamp,
298 int32_t flags,
299 const sp<AMessage>& format,
300 const C2WorkOrdinalStruct& ordinal) {
My Nameac29e592022-03-28 13:53:32 -0700301 bool eos = flags & BUFFER_FLAG_END_OF_STREAM;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700302 if (!buffer && eos) {
303 // TRICKY: we may be violating ordering of the stash here. Because we
304 // don't expect any more emplace() calls after this, the ordering should
305 // not matter.
306 mReorderStash.emplace_back(
307 buffer, notify, timestamp, flags, format, ordinal);
308 } else {
My Nameac29e592022-03-28 13:53:32 -0700309 flags = flags & ~BUFFER_FLAG_END_OF_STREAM;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700310 auto it = mReorderStash.begin();
311 for (; it != mReorderStash.end(); ++it) {
312 if (less(ordinal, it->ordinal)) {
313 break;
314 }
315 }
316 mReorderStash.emplace(it,
317 buffer, notify, timestamp, flags, format, ordinal);
318 if (eos) {
319 mReorderStash.back().flags =
My Nameac29e592022-03-28 13:53:32 -0700320 mReorderStash.back().flags | BUFFER_FLAG_END_OF_STREAM;
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700321 }
322 }
323 while (!mReorderStash.empty() && mReorderStash.size() > mDepth) {
324 mPending.push_back(mReorderStash.front());
325 mReorderStash.pop_front();
326 }
327 ALOGV("[%s] %s: pushToStash -- pending size = %zu", mName, __func__, mPending.size());
328}
329
330OutputBuffers::BufferAction OutputBuffers::popFromStashAndRegister(
331 std::shared_ptr<C2Buffer>* c2Buffer,
332 size_t* index,
333 sp<MediaCodecBuffer>* outBuffer) {
334 if (mPending.empty()) {
335 return SKIP;
336 }
337
338 // Retrieve the first entry.
339 StashEntry &entry = mPending.front();
340
341 *c2Buffer = entry.buffer;
342 sp<AMessage> outputFormat = entry.format;
343
Wonsik Kim3b4349a2020-11-10 11:54:15 -0800344 if (entry.notify && mFormat != outputFormat) {
345 updateSkipCutBuffer(outputFormat);
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800346 // Trigger image data processing to the new format
347 mLastImageData.clear();
Wonsik Kim3b4349a2020-11-10 11:54:15 -0800348 ALOGV("[%s] popFromStashAndRegister: output format reference changed: %p -> %p",
349 mName, mFormat.get(), outputFormat.get());
Wonsik Kim4a3c0462021-03-09 15:45:05 -0800350 ALOGD("[%s] popFromStashAndRegister: at %lldus, output format changed to %s",
351 mName, (long long)entry.timestamp, outputFormat->debugString().c_str());
Wonsik Kim3b4349a2020-11-10 11:54:15 -0800352 setFormat(outputFormat);
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700353 }
354
355 // Flushing mReorderStash because no other buffers should come after output
356 // EOS.
My Nameac29e592022-03-28 13:53:32 -0700357 if (entry.flags & BUFFER_FLAG_END_OF_STREAM) {
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700358 // Flush reorder stash
359 setReorderDepth(0);
360 }
361
362 if (!entry.notify) {
363 mPending.pop_front();
364 return DISCARD;
365 }
366
367 // Try to register the buffer.
368 status_t err = registerBuffer(*c2Buffer, index, outBuffer);
369 if (err != OK) {
370 if (err != WOULD_BLOCK) {
371 return REALLOCATE;
372 }
373 return RETRY;
374 }
375
376 // Append information from the front stash entry to outBuffer.
377 (*outBuffer)->meta()->setInt64("timeUs", entry.timestamp);
378 (*outBuffer)->meta()->setInt32("flags", entry.flags);
Byeongjo Park2eef13e2020-06-12 17:24:21 +0900379 (*outBuffer)->meta()->setInt64("frameIndex", entry.ordinal.frameIndex.peekll());
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700380 ALOGV("[%s] popFromStashAndRegister: "
381 "out buffer index = %zu [%p] => %p + %zu (%lld)",
382 mName, *index, outBuffer->get(),
383 (*outBuffer)->data(), (*outBuffer)->size(),
384 (long long)entry.timestamp);
385
386 // The front entry of mPending will be removed now that the registration
387 // succeeded.
388 mPending.pop_front();
389 return NOTIFY_CLIENT;
390}
391
392bool OutputBuffers::popPending(StashEntry *entry) {
393 if (mPending.empty()) {
394 return false;
395 }
396 *entry = mPending.front();
397 mPending.pop_front();
398 return true;
399}
400
401void OutputBuffers::deferPending(const OutputBuffers::StashEntry &entry) {
402 mPending.push_front(entry);
403}
404
405bool OutputBuffers::hasPending() const {
406 return !mPending.empty();
407}
408
409bool OutputBuffers::less(
410 const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2) const {
411 switch (mKey) {
412 case C2Config::ORDINAL: return o1.frameIndex < o2.frameIndex;
413 case C2Config::TIMESTAMP: return o1.timestamp < o2.timestamp;
414 case C2Config::CUSTOM: return o1.customOrdinal < o2.customOrdinal;
415 default:
416 ALOGD("Unrecognized key; default to timestamp");
417 return o1.frameIndex < o2.frameIndex;
418 }
419}
420
Wonsik Kim469c8342019-04-11 16:46:09 -0700421// LocalBufferPool
422
Wonsik Kim41d83432020-04-27 16:40:49 -0700423constexpr size_t kInitialPoolCapacity = kMaxLinearBufferSize;
424constexpr size_t kMaxPoolCapacity = kMaxLinearBufferSize * 32;
425
426std::shared_ptr<LocalBufferPool> LocalBufferPool::Create() {
427 return std::shared_ptr<LocalBufferPool>(new LocalBufferPool(kInitialPoolCapacity));
Wonsik Kim469c8342019-04-11 16:46:09 -0700428}
429
430sp<ABuffer> LocalBufferPool::newBuffer(size_t capacity) {
431 Mutex::Autolock lock(mMutex);
432 auto it = std::find_if(
433 mPool.begin(), mPool.end(),
434 [capacity](const std::vector<uint8_t> &vec) {
435 return vec.capacity() >= capacity;
436 });
437 if (it != mPool.end()) {
438 sp<ABuffer> buffer = new VectorBuffer(std::move(*it), shared_from_this());
439 mPool.erase(it);
440 return buffer;
441 }
442 if (mUsedSize + capacity > mPoolCapacity) {
443 while (!mPool.empty()) {
444 mUsedSize -= mPool.back().capacity();
445 mPool.pop_back();
446 }
Wonsik Kim41d83432020-04-27 16:40:49 -0700447 while (mUsedSize + capacity > mPoolCapacity && mPoolCapacity * 2 <= kMaxPoolCapacity) {
448 ALOGD("Increasing local buffer pool capacity from %zu to %zu",
449 mPoolCapacity, mPoolCapacity * 2);
450 mPoolCapacity *= 2;
451 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700452 if (mUsedSize + capacity > mPoolCapacity) {
453 ALOGD("mUsedSize = %zu, capacity = %zu, mPoolCapacity = %zu",
454 mUsedSize, capacity, mPoolCapacity);
455 return nullptr;
456 }
457 }
458 std::vector<uint8_t> vec(capacity);
459 mUsedSize += vec.capacity();
460 return new VectorBuffer(std::move(vec), shared_from_this());
461}
462
463LocalBufferPool::VectorBuffer::VectorBuffer(
464 std::vector<uint8_t> &&vec, const std::shared_ptr<LocalBufferPool> &pool)
465 : ABuffer(vec.data(), vec.capacity()),
466 mVec(std::move(vec)),
467 mPool(pool) {
468}
469
470LocalBufferPool::VectorBuffer::~VectorBuffer() {
471 std::shared_ptr<LocalBufferPool> pool = mPool.lock();
472 if (pool) {
473 // If pool is alive, return the vector back to the pool so that
474 // it can be recycled.
475 pool->returnVector(std::move(mVec));
476 }
477}
478
479void LocalBufferPool::returnVector(std::vector<uint8_t> &&vec) {
480 Mutex::Autolock lock(mMutex);
481 mPool.push_front(std::move(vec));
482}
483
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700484// FlexBuffersImpl
485
Wonsik Kim469c8342019-04-11 16:46:09 -0700486size_t FlexBuffersImpl::assignSlot(const sp<Codec2Buffer> &buffer) {
487 for (size_t i = 0; i < mBuffers.size(); ++i) {
488 if (mBuffers[i].clientBuffer == nullptr
489 && mBuffers[i].compBuffer.expired()) {
490 mBuffers[i].clientBuffer = buffer;
491 return i;
492 }
493 }
494 mBuffers.push_back({ buffer, std::weak_ptr<C2Buffer>() });
495 return mBuffers.size() - 1;
496}
497
Wonsik Kim469c8342019-04-11 16:46:09 -0700498bool FlexBuffersImpl::releaseSlot(
499 const sp<MediaCodecBuffer> &buffer,
500 std::shared_ptr<C2Buffer> *c2buffer,
501 bool release) {
502 sp<Codec2Buffer> clientBuffer;
503 size_t index = mBuffers.size();
504 for (size_t i = 0; i < mBuffers.size(); ++i) {
505 if (mBuffers[i].clientBuffer == buffer) {
506 clientBuffer = mBuffers[i].clientBuffer;
507 if (release) {
508 mBuffers[i].clientBuffer.clear();
509 }
510 index = i;
511 break;
512 }
513 }
514 if (clientBuffer == nullptr) {
515 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
516 return false;
517 }
518 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
519 if (!result) {
520 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700521 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700522 mBuffers[index].compBuffer = result;
523 }
524 if (c2buffer) {
525 *c2buffer = result;
526 }
527 return true;
528}
529
530bool FlexBuffersImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
531 for (size_t i = 0; i < mBuffers.size(); ++i) {
532 std::shared_ptr<C2Buffer> compBuffer =
533 mBuffers[i].compBuffer.lock();
534 if (!compBuffer || compBuffer != c2buffer) {
535 continue;
536 }
537 mBuffers[i].compBuffer.reset();
538 ALOGV("[%s] codec released buffer #%zu", mName, i);
539 return true;
540 }
541 ALOGV("[%s] codec released an unknown buffer", mName);
542 return false;
543}
544
545void FlexBuffersImpl::flush() {
546 ALOGV("[%s] buffers are flushed %zu", mName, mBuffers.size());
547 mBuffers.clear();
548}
549
Wonsik Kim0487b782020-10-28 11:45:50 -0700550size_t FlexBuffersImpl::numActiveSlots() const {
Wonsik Kim469c8342019-04-11 16:46:09 -0700551 return std::count_if(
552 mBuffers.begin(), mBuffers.end(),
553 [](const Entry &entry) {
Wonsik Kim0487b782020-10-28 11:45:50 -0700554 return (entry.clientBuffer != nullptr
555 || !entry.compBuffer.expired());
Wonsik Kim469c8342019-04-11 16:46:09 -0700556 });
557}
558
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700559size_t FlexBuffersImpl::numComponentBuffers() const {
560 return std::count_if(
561 mBuffers.begin(), mBuffers.end(),
562 [](const Entry &entry) {
563 return !entry.compBuffer.expired();
564 });
565}
566
Wonsik Kim469c8342019-04-11 16:46:09 -0700567// BuffersArrayImpl
568
569void BuffersArrayImpl::initialize(
570 const FlexBuffersImpl &impl,
571 size_t minSize,
572 std::function<sp<Codec2Buffer>()> allocate) {
573 mImplName = impl.mImplName + "[N]";
574 mName = mImplName.c_str();
575 for (size_t i = 0; i < impl.mBuffers.size(); ++i) {
576 sp<Codec2Buffer> clientBuffer = impl.mBuffers[i].clientBuffer;
577 bool ownedByClient = (clientBuffer != nullptr);
578 if (!ownedByClient) {
579 clientBuffer = allocate();
580 }
581 mBuffers.push_back({ clientBuffer, impl.mBuffers[i].compBuffer, ownedByClient });
582 }
583 ALOGV("[%s] converted %zu buffers to array mode of %zu", mName, mBuffers.size(), minSize);
584 for (size_t i = impl.mBuffers.size(); i < minSize; ++i) {
585 mBuffers.push_back({ allocate(), std::weak_ptr<C2Buffer>(), false });
586 }
587}
588
589status_t BuffersArrayImpl::grabBuffer(
590 size_t *index,
591 sp<Codec2Buffer> *buffer,
592 std::function<bool(const sp<Codec2Buffer> &)> match) {
593 // allBuffersDontMatch remains true if all buffers are available but
594 // match() returns false for every buffer.
595 bool allBuffersDontMatch = true;
596 for (size_t i = 0; i < mBuffers.size(); ++i) {
597 if (!mBuffers[i].ownedByClient && mBuffers[i].compBuffer.expired()) {
598 if (match(mBuffers[i].clientBuffer)) {
599 mBuffers[i].ownedByClient = true;
600 *buffer = mBuffers[i].clientBuffer;
601 (*buffer)->meta()->clear();
602 (*buffer)->setRange(0, (*buffer)->capacity());
603 *index = i;
604 return OK;
605 }
606 } else {
607 allBuffersDontMatch = false;
608 }
609 }
610 return allBuffersDontMatch ? NO_MEMORY : WOULD_BLOCK;
611}
612
613bool BuffersArrayImpl::returnBuffer(
614 const sp<MediaCodecBuffer> &buffer,
615 std::shared_ptr<C2Buffer> *c2buffer,
616 bool release) {
617 sp<Codec2Buffer> clientBuffer;
618 size_t index = mBuffers.size();
619 for (size_t i = 0; i < mBuffers.size(); ++i) {
620 if (mBuffers[i].clientBuffer == buffer) {
621 if (!mBuffers[i].ownedByClient) {
622 ALOGD("[%s] Client returned a buffer it does not own according to our record: %zu",
623 mName, i);
624 }
625 clientBuffer = mBuffers[i].clientBuffer;
626 if (release) {
627 mBuffers[i].ownedByClient = false;
628 }
629 index = i;
630 break;
631 }
632 }
633 if (clientBuffer == nullptr) {
634 ALOGV("[%s] %s: No matching buffer found", mName, __func__);
635 return false;
636 }
637 ALOGV("[%s] %s: matching buffer found (index=%zu)", mName, __func__, index);
638 std::shared_ptr<C2Buffer> result = mBuffers[index].compBuffer.lock();
639 if (!result) {
640 result = clientBuffer->asC2Buffer();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700641 clientBuffer->clearC2BufferRefs();
Wonsik Kim469c8342019-04-11 16:46:09 -0700642 mBuffers[index].compBuffer = result;
643 }
644 if (c2buffer) {
645 *c2buffer = result;
646 }
647 return true;
648}
649
650bool BuffersArrayImpl::expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer) {
651 for (size_t i = 0; i < mBuffers.size(); ++i) {
652 std::shared_ptr<C2Buffer> compBuffer =
653 mBuffers[i].compBuffer.lock();
654 if (!compBuffer) {
655 continue;
656 }
657 if (c2buffer == compBuffer) {
658 if (mBuffers[i].ownedByClient) {
659 // This should not happen.
660 ALOGD("[%s] codec released a buffer owned by client "
661 "(index %zu)", mName, i);
662 }
663 mBuffers[i].compBuffer.reset();
664 ALOGV("[%s] codec released buffer #%zu(array mode)", mName, i);
665 return true;
666 }
667 }
668 ALOGV("[%s] codec released an unknown buffer (array mode)", mName);
669 return false;
670}
671
672void BuffersArrayImpl::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
673 array->clear();
674 for (const Entry &entry : mBuffers) {
675 array->push(entry.clientBuffer);
676 }
677}
678
679void BuffersArrayImpl::flush() {
680 for (Entry &entry : mBuffers) {
681 entry.ownedByClient = false;
682 }
683}
684
685void BuffersArrayImpl::realloc(std::function<sp<Codec2Buffer>()> alloc) {
686 size_t size = mBuffers.size();
687 mBuffers.clear();
688 for (size_t i = 0; i < size; ++i) {
689 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
690 }
691}
692
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700693void BuffersArrayImpl::grow(
694 size_t newSize, std::function<sp<Codec2Buffer>()> alloc) {
695 CHECK_LT(mBuffers.size(), newSize);
696 while (mBuffers.size() < newSize) {
697 mBuffers.push_back({ alloc(), std::weak_ptr<C2Buffer>(), false });
698 }
699}
700
Wonsik Kim0487b782020-10-28 11:45:50 -0700701size_t BuffersArrayImpl::numActiveSlots() const {
Wonsik Kim469c8342019-04-11 16:46:09 -0700702 return std::count_if(
703 mBuffers.begin(), mBuffers.end(),
704 [](const Entry &entry) {
Wonsik Kim0487b782020-10-28 11:45:50 -0700705 return entry.ownedByClient || !entry.compBuffer.expired();
Wonsik Kim469c8342019-04-11 16:46:09 -0700706 });
707}
708
Wonsik Kima39882b2019-06-20 16:13:56 -0700709size_t BuffersArrayImpl::arraySize() const {
710 return mBuffers.size();
711}
712
Wonsik Kim469c8342019-04-11 16:46:09 -0700713// InputBuffersArray
714
715void InputBuffersArray::initialize(
716 const FlexBuffersImpl &impl,
717 size_t minSize,
718 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700719 mAllocate = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -0700720 mImpl.initialize(impl, minSize, allocate);
721}
722
723void InputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
724 mImpl.getArray(array);
725}
726
727bool InputBuffersArray::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
728 sp<Codec2Buffer> c2Buffer;
729 status_t err = mImpl.grabBuffer(index, &c2Buffer);
730 if (err == OK) {
731 c2Buffer->setFormat(mFormat);
732 handleImageData(c2Buffer);
733 *buffer = c2Buffer;
734 return true;
735 }
736 return false;
737}
738
739bool InputBuffersArray::releaseBuffer(
740 const sp<MediaCodecBuffer> &buffer,
741 std::shared_ptr<C2Buffer> *c2buffer,
742 bool release) {
743 return mImpl.returnBuffer(buffer, c2buffer, release);
744}
745
746bool InputBuffersArray::expireComponentBuffer(
747 const std::shared_ptr<C2Buffer> &c2buffer) {
748 return mImpl.expireComponentBuffer(c2buffer);
749}
750
751void InputBuffersArray::flush() {
752 mImpl.flush();
753}
754
Wonsik Kim0487b782020-10-28 11:45:50 -0700755size_t InputBuffersArray::numActiveSlots() const {
756 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700757}
758
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700759sp<Codec2Buffer> InputBuffersArray::createNewBuffer() {
760 return mAllocate();
761}
762
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800763// SlotInputBuffers
764
765bool SlotInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
766 sp<Codec2Buffer> newBuffer = createNewBuffer();
767 *index = mImpl.assignSlot(newBuffer);
768 *buffer = newBuffer;
769 return true;
770}
771
772bool SlotInputBuffers::releaseBuffer(
773 const sp<MediaCodecBuffer> &buffer,
774 std::shared_ptr<C2Buffer> *c2buffer,
775 bool release) {
776 return mImpl.releaseSlot(buffer, c2buffer, release);
777}
778
779bool SlotInputBuffers::expireComponentBuffer(
780 const std::shared_ptr<C2Buffer> &c2buffer) {
781 return mImpl.expireComponentBuffer(c2buffer);
782}
783
784void SlotInputBuffers::flush() {
785 mImpl.flush();
786}
787
788std::unique_ptr<InputBuffers> SlotInputBuffers::toArrayMode(size_t) {
789 TRESPASS("Array mode should not be called at non-legacy mode");
790 return nullptr;
791}
792
Wonsik Kim0487b782020-10-28 11:45:50 -0700793size_t SlotInputBuffers::numActiveSlots() const {
794 return mImpl.numActiveSlots();
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800795}
796
797sp<Codec2Buffer> SlotInputBuffers::createNewBuffer() {
798 return new DummyContainerBuffer{mFormat, nullptr};
799}
800
Wonsik Kim469c8342019-04-11 16:46:09 -0700801// LinearInputBuffers
802
803bool LinearInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700804 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700805 if (newBuffer == nullptr) {
806 return false;
807 }
808 *index = mImpl.assignSlot(newBuffer);
809 *buffer = newBuffer;
810 return true;
811}
812
813bool LinearInputBuffers::releaseBuffer(
814 const sp<MediaCodecBuffer> &buffer,
815 std::shared_ptr<C2Buffer> *c2buffer,
816 bool release) {
817 return mImpl.releaseSlot(buffer, c2buffer, release);
818}
819
820bool LinearInputBuffers::expireComponentBuffer(
821 const std::shared_ptr<C2Buffer> &c2buffer) {
822 return mImpl.expireComponentBuffer(c2buffer);
823}
824
825void LinearInputBuffers::flush() {
826 // This is no-op by default unless we're in array mode where we need to keep
827 // track of the flushed work.
828 mImpl.flush();
829}
830
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700831std::unique_ptr<InputBuffers> LinearInputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -0700832 std::unique_ptr<InputBuffersArray> array(
833 new InputBuffersArray(mComponentName.c_str(), "1D-Input[N]"));
834 array->setPool(mPool);
835 array->setFormat(mFormat);
836 array->initialize(
837 mImpl,
838 size,
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700839 [pool = mPool, format = mFormat] () -> sp<Codec2Buffer> {
840 return Alloc(pool, format);
841 });
Wonsik Kim469c8342019-04-11 16:46:09 -0700842 return std::move(array);
843}
844
Wonsik Kim0487b782020-10-28 11:45:50 -0700845size_t LinearInputBuffers::numActiveSlots() const {
846 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -0700847}
848
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700849// static
850sp<Codec2Buffer> LinearInputBuffers::Alloc(
851 const std::shared_ptr<C2BlockPool> &pool, const sp<AMessage> &format) {
852 int32_t capacity = kLinearBufferSize;
853 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
854 if ((size_t)capacity > kMaxLinearBufferSize) {
855 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
856 capacity = kMaxLinearBufferSize;
857 }
858
Wonsik Kim666604a2020-05-14 16:57:49 -0700859 int64_t usageValue = 0;
860 (void)format->findInt64("android._C2MemoryUsage", &usageValue);
861 C2MemoryUsage usage{usageValue | C2MemoryUsage::CPU_READ | C2MemoryUsage::CPU_WRITE};
Wonsik Kim469c8342019-04-11 16:46:09 -0700862 std::shared_ptr<C2LinearBlock> block;
863
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700864 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700865 if (err != C2_OK) {
866 return nullptr;
867 }
868
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700869 return LinearBlockBuffer::Allocate(format, block);
870}
871
872sp<Codec2Buffer> LinearInputBuffers::createNewBuffer() {
873 return Alloc(mPool, mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -0700874}
875
876// EncryptedLinearInputBuffers
877
878EncryptedLinearInputBuffers::EncryptedLinearInputBuffers(
879 bool secure,
880 const sp<MemoryDealer> &dealer,
881 const sp<ICrypto> &crypto,
882 int32_t heapSeqNum,
883 size_t capacity,
884 size_t numInputSlots,
885 const char *componentName, const char *name)
886 : LinearInputBuffers(componentName, name),
887 mUsage({0, 0}),
888 mDealer(dealer),
889 mCrypto(crypto),
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700890 mMemoryVector(new std::vector<Entry>){
Wonsik Kim469c8342019-04-11 16:46:09 -0700891 if (secure) {
892 mUsage = { C2MemoryUsage::READ_PROTECTED, 0 };
893 } else {
894 mUsage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
895 }
896 for (size_t i = 0; i < numInputSlots; ++i) {
897 sp<IMemory> memory = mDealer->allocate(capacity);
898 if (memory == nullptr) {
899 ALOGD("[%s] Failed to allocate memory from dealer: only %zu slots allocated",
900 mName, i);
901 break;
902 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700903 mMemoryVector->push_back({std::weak_ptr<C2LinearBlock>(), memory, heapSeqNum});
Wonsik Kim469c8342019-04-11 16:46:09 -0700904 }
905}
906
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700907std::unique_ptr<InputBuffers> EncryptedLinearInputBuffers::toArrayMode(size_t size) {
908 std::unique_ptr<InputBuffersArray> array(
909 new InputBuffersArray(mComponentName.c_str(), "1D-EncryptedInput[N]"));
910 array->setPool(mPool);
911 array->setFormat(mFormat);
912 array->initialize(
913 mImpl,
914 size,
915 [pool = mPool,
916 format = mFormat,
917 usage = mUsage,
918 memoryVector = mMemoryVector] () -> sp<Codec2Buffer> {
919 return Alloc(pool, format, usage, memoryVector);
920 });
921 return std::move(array);
922}
923
924
925// static
926sp<Codec2Buffer> EncryptedLinearInputBuffers::Alloc(
927 const std::shared_ptr<C2BlockPool> &pool,
928 const sp<AMessage> &format,
929 C2MemoryUsage usage,
930 const std::shared_ptr<std::vector<EncryptedLinearInputBuffers::Entry>> &memoryVector) {
931 int32_t capacity = kLinearBufferSize;
932 (void)format->findInt32(KEY_MAX_INPUT_SIZE, &capacity);
933 if ((size_t)capacity > kMaxLinearBufferSize) {
934 ALOGD("client requested %d, capped to %zu", capacity, kMaxLinearBufferSize);
935 capacity = kMaxLinearBufferSize;
936 }
937
Wonsik Kim469c8342019-04-11 16:46:09 -0700938 sp<IMemory> memory;
939 size_t slot = 0;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700940 int32_t heapSeqNum = -1;
941 for (; slot < memoryVector->size(); ++slot) {
942 if (memoryVector->at(slot).block.expired()) {
943 memory = memoryVector->at(slot).memory;
944 heapSeqNum = memoryVector->at(slot).heapSeqNum;
Wonsik Kim469c8342019-04-11 16:46:09 -0700945 break;
946 }
947 }
948 if (memory == nullptr) {
949 return nullptr;
950 }
951
David Stevens94b608f2021-07-29 15:04:14 +0900952 int64_t usageValue = 0;
953 (void)format->findInt64("android._C2MemoryUsage", &usageValue);
954 usage = C2MemoryUsage(usage.expected | usageValue);
955
Wonsik Kim469c8342019-04-11 16:46:09 -0700956 std::shared_ptr<C2LinearBlock> block;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700957 c2_status_t err = pool->fetchLinearBlock(capacity, usage, &block);
Wonsik Kim469c8342019-04-11 16:46:09 -0700958 if (err != C2_OK || block == nullptr) {
959 return nullptr;
960 }
961
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700962 memoryVector->at(slot).block = block;
963 return new EncryptedLinearBlockBuffer(format, block, memory, heapSeqNum);
964}
965
966sp<Codec2Buffer> EncryptedLinearInputBuffers::createNewBuffer() {
967 // TODO: android_2020
968 return nullptr;
Wonsik Kim469c8342019-04-11 16:46:09 -0700969}
970
971// GraphicMetadataInputBuffers
972
973GraphicMetadataInputBuffers::GraphicMetadataInputBuffers(
974 const char *componentName, const char *name)
975 : InputBuffers(componentName, name),
976 mImpl(mName),
977 mStore(GetCodec2PlatformAllocatorStore()) { }
978
979bool GraphicMetadataInputBuffers::requestNewBuffer(
980 size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700981 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -0700982 if (newBuffer == nullptr) {
983 return false;
984 }
985 *index = mImpl.assignSlot(newBuffer);
986 *buffer = newBuffer;
987 return true;
988}
989
990bool GraphicMetadataInputBuffers::releaseBuffer(
991 const sp<MediaCodecBuffer> &buffer,
992 std::shared_ptr<C2Buffer> *c2buffer,
993 bool release) {
994 return mImpl.releaseSlot(buffer, c2buffer, release);
995}
996
997bool GraphicMetadataInputBuffers::expireComponentBuffer(
998 const std::shared_ptr<C2Buffer> &c2buffer) {
999 return mImpl.expireComponentBuffer(c2buffer);
1000}
1001
1002void GraphicMetadataInputBuffers::flush() {
1003 // This is no-op by default unless we're in array mode where we need to keep
1004 // track of the flushed work.
1005}
1006
1007std::unique_ptr<InputBuffers> GraphicMetadataInputBuffers::toArrayMode(
1008 size_t size) {
1009 std::shared_ptr<C2Allocator> alloc;
1010 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
1011 if (err != C2_OK) {
1012 return nullptr;
1013 }
1014 std::unique_ptr<InputBuffersArray> array(
1015 new InputBuffersArray(mComponentName.c_str(), "2D-MetaInput[N]"));
1016 array->setPool(mPool);
1017 array->setFormat(mFormat);
1018 array->initialize(
1019 mImpl,
1020 size,
1021 [format = mFormat, alloc]() -> sp<Codec2Buffer> {
1022 return new GraphicMetadataBuffer(format, alloc);
1023 });
1024 return std::move(array);
1025}
1026
Wonsik Kim0487b782020-10-28 11:45:50 -07001027size_t GraphicMetadataInputBuffers::numActiveSlots() const {
1028 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001029}
1030
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001031sp<Codec2Buffer> GraphicMetadataInputBuffers::createNewBuffer() {
1032 std::shared_ptr<C2Allocator> alloc;
1033 c2_status_t err = mStore->fetchAllocator(mPool->getAllocatorId(), &alloc);
1034 if (err != C2_OK) {
1035 return nullptr;
1036 }
1037 return new GraphicMetadataBuffer(mFormat, alloc);
1038}
1039
Wonsik Kim469c8342019-04-11 16:46:09 -07001040// GraphicInputBuffers
1041
1042GraphicInputBuffers::GraphicInputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -07001043 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -07001044 : InputBuffers(componentName, name),
1045 mImpl(mName),
Wonsik Kim41d83432020-04-27 16:40:49 -07001046 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -07001047
1048bool GraphicInputBuffers::requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001049 sp<Codec2Buffer> newBuffer = createNewBuffer();
Wonsik Kim469c8342019-04-11 16:46:09 -07001050 if (newBuffer == nullptr) {
1051 return false;
1052 }
1053 *index = mImpl.assignSlot(newBuffer);
1054 handleImageData(newBuffer);
1055 *buffer = newBuffer;
1056 return true;
1057}
1058
1059bool GraphicInputBuffers::releaseBuffer(
1060 const sp<MediaCodecBuffer> &buffer,
1061 std::shared_ptr<C2Buffer> *c2buffer,
1062 bool release) {
1063 return mImpl.releaseSlot(buffer, c2buffer, release);
1064}
1065
1066bool GraphicInputBuffers::expireComponentBuffer(
1067 const std::shared_ptr<C2Buffer> &c2buffer) {
1068 return mImpl.expireComponentBuffer(c2buffer);
1069}
1070
1071void GraphicInputBuffers::flush() {
1072 // This is no-op by default unless we're in array mode where we need to keep
1073 // track of the flushed work.
1074}
1075
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001076static uint32_t extractPixelFormat(const sp<AMessage> &format) {
1077 int32_t frameworkColorFormat = 0;
1078 if (!format->findInt32("android._color-format", &frameworkColorFormat)) {
1079 return PIXEL_FORMAT_UNKNOWN;
1080 }
1081 uint32_t pixelFormat = PIXEL_FORMAT_UNKNOWN;
1082 if (C2Mapper::mapPixelFormatFrameworkToCodec(frameworkColorFormat, &pixelFormat)) {
1083 return pixelFormat;
1084 }
1085 return PIXEL_FORMAT_UNKNOWN;
1086}
1087
Wonsik Kim469c8342019-04-11 16:46:09 -07001088std::unique_ptr<InputBuffers> GraphicInputBuffers::toArrayMode(size_t size) {
1089 std::unique_ptr<InputBuffersArray> array(
1090 new InputBuffersArray(mComponentName.c_str(), "2D-BB-Input[N]"));
1091 array->setPool(mPool);
1092 array->setFormat(mFormat);
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001093 uint32_t pixelFormat = extractPixelFormat(mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -07001094 array->initialize(
1095 mImpl,
1096 size,
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001097 [pool = mPool, format = mFormat, lbp = mLocalBufferPool, pixelFormat]()
1098 -> sp<Codec2Buffer> {
Wonsik Kim469c8342019-04-11 16:46:09 -07001099 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
David Stevens94b608f2021-07-29 15:04:14 +09001100 return AllocateInputGraphicBuffer(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001101 pool, format, pixelFormat, usage, lbp);
Wonsik Kim469c8342019-04-11 16:46:09 -07001102 });
1103 return std::move(array);
1104}
1105
Wonsik Kim0487b782020-10-28 11:45:50 -07001106size_t GraphicInputBuffers::numActiveSlots() const {
1107 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001108}
1109
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001110sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
David Stevens94b608f2021-07-29 15:04:14 +09001111 C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
1112 return AllocateInputGraphicBuffer(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -07001113 mPool, mFormat, extractPixelFormat(mFormat), usage, mLocalBufferPool);
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001114}
1115
Wonsik Kim469c8342019-04-11 16:46:09 -07001116// OutputBuffersArray
1117
1118void OutputBuffersArray::initialize(
1119 const FlexBuffersImpl &impl,
1120 size_t minSize,
1121 std::function<sp<Codec2Buffer>()> allocate) {
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001122 mAlloc = allocate;
Wonsik Kim469c8342019-04-11 16:46:09 -07001123 mImpl.initialize(impl, minSize, allocate);
1124}
1125
1126status_t OutputBuffersArray::registerBuffer(
1127 const std::shared_ptr<C2Buffer> &buffer,
1128 size_t *index,
1129 sp<MediaCodecBuffer> *clientBuffer) {
1130 sp<Codec2Buffer> c2Buffer;
1131 status_t err = mImpl.grabBuffer(
1132 index,
1133 &c2Buffer,
1134 [buffer](const sp<Codec2Buffer> &clientBuffer) {
1135 return clientBuffer->canCopy(buffer);
1136 });
1137 if (err == WOULD_BLOCK) {
1138 ALOGV("[%s] buffers temporarily not available", mName);
1139 return err;
1140 } else if (err != OK) {
1141 ALOGD("[%s] grabBuffer failed: %d", mName, err);
1142 return err;
1143 }
1144 c2Buffer->setFormat(mFormat);
Wonsik Kim6f23cfc2021-09-24 05:45:52 -07001145 if (!convert(buffer, &c2Buffer) && !c2Buffer->copy(buffer)) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001146 ALOGD("[%s] copy buffer failed", mName);
1147 return WOULD_BLOCK;
1148 }
1149 submit(c2Buffer);
1150 handleImageData(c2Buffer);
1151 *clientBuffer = c2Buffer;
1152 ALOGV("[%s] grabbed buffer %zu", mName, *index);
1153 return OK;
1154}
1155
1156status_t OutputBuffersArray::registerCsd(
1157 const C2StreamInitDataInfo::output *csd,
1158 size_t *index,
1159 sp<MediaCodecBuffer> *clientBuffer) {
1160 sp<Codec2Buffer> c2Buffer;
1161 status_t err = mImpl.grabBuffer(
1162 index,
1163 &c2Buffer,
1164 [csd](const sp<Codec2Buffer> &clientBuffer) {
1165 return clientBuffer->base() != nullptr
1166 && clientBuffer->capacity() >= csd->flexCount();
1167 });
1168 if (err != OK) {
1169 return err;
1170 }
1171 memcpy(c2Buffer->base(), csd->m.value, csd->flexCount());
1172 c2Buffer->setRange(0, csd->flexCount());
1173 c2Buffer->setFormat(mFormat);
1174 *clientBuffer = c2Buffer;
1175 return OK;
1176}
1177
1178bool OutputBuffersArray::releaseBuffer(
1179 const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) {
1180 return mImpl.returnBuffer(buffer, c2buffer, true);
1181}
1182
1183void OutputBuffersArray::flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1184 (void)flushedWork;
1185 mImpl.flush();
1186 if (mSkipCutBuffer != nullptr) {
1187 mSkipCutBuffer->clear();
1188 }
1189}
1190
1191void OutputBuffersArray::getArray(Vector<sp<MediaCodecBuffer>> *array) const {
1192 mImpl.getArray(array);
1193}
1194
Wonsik Kim0487b782020-10-28 11:45:50 -07001195size_t OutputBuffersArray::numActiveSlots() const {
1196 return mImpl.numActiveSlots();
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001197}
1198
Wonsik Kim469c8342019-04-11 16:46:09 -07001199void OutputBuffersArray::realloc(const std::shared_ptr<C2Buffer> &c2buffer) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001200 switch (c2buffer->data().type()) {
1201 case C2BufferData::LINEAR: {
1202 uint32_t size = kLinearBufferSize;
Nick Desaulniersd09eaea2019-10-07 20:19:39 -07001203 const std::vector<C2ConstLinearBlock> &linear_blocks = c2buffer->data().linearBlocks();
1204 const uint32_t block_size = linear_blocks.front().size();
1205 if (block_size < kMaxLinearBufferSize / 2) {
1206 size = block_size * 2;
Wonsik Kim469c8342019-04-11 16:46:09 -07001207 } else {
1208 size = kMaxLinearBufferSize;
1209 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001210 mAlloc = [format = mFormat, size] {
Wonsik Kim469c8342019-04-11 16:46:09 -07001211 return new LocalLinearBuffer(format, new ABuffer(size));
1212 };
Wonsik Kima39882b2019-06-20 16:13:56 -07001213 ALOGD("[%s] reallocating with linear buffer of size %u", mName, size);
Wonsik Kim469c8342019-04-11 16:46:09 -07001214 break;
1215 }
1216
Wonsik Kima39882b2019-06-20 16:13:56 -07001217 case C2BufferData::GRAPHIC: {
1218 // This is only called for RawGraphicOutputBuffers.
1219 mAlloc = [format = mFormat,
Wonsik Kim41d83432020-04-27 16:40:49 -07001220 lbp = LocalBufferPool::Create()] {
Wonsik Kima39882b2019-06-20 16:13:56 -07001221 return ConstGraphicBlockBuffer::AllocateEmpty(
1222 format,
1223 [lbp](size_t capacity) {
1224 return lbp->newBuffer(capacity);
1225 });
1226 };
1227 ALOGD("[%s] reallocating with graphic buffer: format = %s",
1228 mName, mFormat->debugString().c_str());
1229 break;
1230 }
Wonsik Kim469c8342019-04-11 16:46:09 -07001231
1232 case C2BufferData::INVALID: [[fallthrough]];
1233 case C2BufferData::LINEAR_CHUNKS: [[fallthrough]];
1234 case C2BufferData::GRAPHIC_CHUNKS: [[fallthrough]];
1235 default:
1236 ALOGD("Unsupported type: %d", (int)c2buffer->data().type());
1237 return;
1238 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001239 mImpl.realloc(mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -07001240}
1241
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001242void OutputBuffersArray::grow(size_t newSize) {
1243 mImpl.grow(newSize, mAlloc);
Wonsik Kim469c8342019-04-11 16:46:09 -07001244}
1245
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001246void OutputBuffersArray::transferFrom(OutputBuffers* source) {
1247 mFormat = source->mFormat;
1248 mSkipCutBuffer = source->mSkipCutBuffer;
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001249 mPending = std::move(source->mPending);
1250 mReorderStash = std::move(source->mReorderStash);
1251 mDepth = source->mDepth;
1252 mKey = source->mKey;
1253}
1254
Wonsik Kim469c8342019-04-11 16:46:09 -07001255// FlexOutputBuffers
1256
1257status_t FlexOutputBuffers::registerBuffer(
1258 const std::shared_ptr<C2Buffer> &buffer,
1259 size_t *index,
1260 sp<MediaCodecBuffer> *clientBuffer) {
Wonsik Kim6f23cfc2021-09-24 05:45:52 -07001261 sp<Codec2Buffer> newBuffer;
1262 if (!convert(buffer, &newBuffer)) {
1263 newBuffer = wrap(buffer);
1264 if (newBuffer == nullptr) {
1265 return NO_MEMORY;
1266 }
Wonsik Kim360ba0a2022-05-23 15:38:21 -07001267 newBuffer->setFormat(mFormat);
Wonsik Kim469c8342019-04-11 16:46:09 -07001268 }
Wonsik Kim469c8342019-04-11 16:46:09 -07001269 *index = mImpl.assignSlot(newBuffer);
1270 handleImageData(newBuffer);
1271 *clientBuffer = newBuffer;
1272 ALOGV("[%s] registered buffer %zu", mName, *index);
1273 return OK;
1274}
1275
1276status_t FlexOutputBuffers::registerCsd(
1277 const C2StreamInitDataInfo::output *csd,
1278 size_t *index,
1279 sp<MediaCodecBuffer> *clientBuffer) {
1280 sp<Codec2Buffer> newBuffer = new LocalLinearBuffer(
1281 mFormat, ABuffer::CreateAsCopy(csd->m.value, csd->flexCount()));
1282 *index = mImpl.assignSlot(newBuffer);
1283 *clientBuffer = newBuffer;
1284 return OK;
1285}
1286
1287bool FlexOutputBuffers::releaseBuffer(
1288 const sp<MediaCodecBuffer> &buffer,
1289 std::shared_ptr<C2Buffer> *c2buffer) {
1290 return mImpl.releaseSlot(buffer, c2buffer, true);
1291}
1292
1293void FlexOutputBuffers::flush(
1294 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1295 (void) flushedWork;
1296 // This is no-op by default unless we're in array mode where we need to keep
1297 // track of the flushed work.
1298}
1299
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001300std::unique_ptr<OutputBuffersArray> FlexOutputBuffers::toArrayMode(size_t size) {
Wonsik Kim469c8342019-04-11 16:46:09 -07001301 std::unique_ptr<OutputBuffersArray> array(new OutputBuffersArray(mComponentName.c_str()));
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001302 array->transferFrom(this);
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001303 std::function<sp<Codec2Buffer>()> alloc = getAlloc();
1304 array->initialize(mImpl, size, alloc);
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001305 return array;
Wonsik Kim469c8342019-04-11 16:46:09 -07001306}
1307
Wonsik Kim0487b782020-10-28 11:45:50 -07001308size_t FlexOutputBuffers::numActiveSlots() const {
1309 return mImpl.numActiveSlots();
Wonsik Kim469c8342019-04-11 16:46:09 -07001310}
1311
1312// LinearOutputBuffers
1313
1314void LinearOutputBuffers::flush(
1315 const std::list<std::unique_ptr<C2Work>> &flushedWork) {
1316 if (mSkipCutBuffer != nullptr) {
1317 mSkipCutBuffer->clear();
1318 }
1319 FlexOutputBuffers::flush(flushedWork);
1320}
1321
1322sp<Codec2Buffer> LinearOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1323 if (buffer == nullptr) {
1324 ALOGV("[%s] using a dummy buffer", mName);
1325 return new LocalLinearBuffer(mFormat, new ABuffer(0));
1326 }
1327 if (buffer->data().type() != C2BufferData::LINEAR) {
1328 ALOGV("[%s] non-linear buffer %d", mName, buffer->data().type());
1329 // We expect linear output buffers from the component.
1330 return nullptr;
1331 }
1332 if (buffer->data().linearBlocks().size() != 1u) {
1333 ALOGV("[%s] no linear buffers", mName);
1334 // We expect one and only one linear block from the component.
1335 return nullptr;
1336 }
1337 sp<Codec2Buffer> clientBuffer = ConstLinearBlockBuffer::Allocate(mFormat, buffer);
1338 if (clientBuffer == nullptr) {
1339 ALOGD("[%s] ConstLinearBlockBuffer::Allocate failed", mName);
1340 return nullptr;
1341 }
1342 submit(clientBuffer);
1343 return clientBuffer;
1344}
1345
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001346std::function<sp<Codec2Buffer>()> LinearOutputBuffers::getAlloc() {
1347 return [format = mFormat]{
1348 // TODO: proper max output size
1349 return new LocalLinearBuffer(format, new ABuffer(kLinearBufferSize));
1350 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001351}
1352
1353// GraphicOutputBuffers
1354
1355sp<Codec2Buffer> GraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1356 return new DummyContainerBuffer(mFormat, buffer);
1357}
1358
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001359std::function<sp<Codec2Buffer>()> GraphicOutputBuffers::getAlloc() {
1360 return [format = mFormat]{
1361 return new DummyContainerBuffer(format);
1362 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001363}
1364
1365// RawGraphicOutputBuffers
1366
1367RawGraphicOutputBuffers::RawGraphicOutputBuffers(
Wonsik Kim41d83432020-04-27 16:40:49 -07001368 const char *componentName, const char *name)
Wonsik Kim469c8342019-04-11 16:46:09 -07001369 : FlexOutputBuffers(componentName, name),
Wonsik Kim41d83432020-04-27 16:40:49 -07001370 mLocalBufferPool(LocalBufferPool::Create()) { }
Wonsik Kim469c8342019-04-11 16:46:09 -07001371
1372sp<Codec2Buffer> RawGraphicOutputBuffers::wrap(const std::shared_ptr<C2Buffer> &buffer) {
1373 if (buffer == nullptr) {
Wonsik Kim6f116902021-07-14 08:58:07 -07001374 return new Codec2Buffer(mFormat, new ABuffer(nullptr, 0));
Wonsik Kim469c8342019-04-11 16:46:09 -07001375 } else {
1376 return ConstGraphicBlockBuffer::Allocate(
1377 mFormat,
1378 buffer,
1379 [lbp = mLocalBufferPool](size_t capacity) {
1380 return lbp->newBuffer(capacity);
1381 });
1382 }
1383}
1384
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001385std::function<sp<Codec2Buffer>()> RawGraphicOutputBuffers::getAlloc() {
1386 return [format = mFormat, lbp = mLocalBufferPool]{
1387 return ConstGraphicBlockBuffer::AllocateEmpty(
1388 format,
1389 [lbp](size_t capacity) {
1390 return lbp->newBuffer(capacity);
1391 });
1392 };
Wonsik Kim469c8342019-04-11 16:46:09 -07001393}
1394
1395} // namespace android