blob: 164a1e07cbbf6dc254402d1344e57fa337b53f0d [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
2 * Copyright 2018, 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 "Codec2Buffer"
My Name6bd9a7d2022-03-25 12:37:58 -070019#define ATRACE_TAG ATRACE_TAG_VIDEO
Pawin Vongmasa36653902018-11-15 00:10:25 -080020#include <utils/Log.h>
My Name6bd9a7d2022-03-25 12:37:58 -070021#include <utils/Trace.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080022
Wonsik Kima79c5522022-01-18 16:29:24 -080023#include <aidl/android/hardware/graphics/common/Cta861_3.h>
24#include <aidl/android/hardware/graphics/common/Smpte2086.h>
Wonsik Kim89814312023-02-01 10:46:16 -080025#include <android-base/no_destructor.h>
bohua222c0b2021-01-12 18:54:53 -080026#include <android-base/properties.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070027#include <android/hardware/cas/native/1.0/types.h>
28#include <android/hardware/drm/1.0/types.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080029#include <hidlmemory/FrameworkUtils.h>
30#include <media/hardware/HardwareAPI.h>
Robert Shih895fba92019-07-16 16:29:44 -070031#include <media/stagefright/CodecBase.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080032#include <media/stagefright/MediaCodecConstants.h>
33#include <media/stagefright/foundation/ABuffer.h>
34#include <media/stagefright/foundation/AMessage.h>
35#include <media/stagefright/foundation/AUtils.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070036#include <mediadrm/ICrypto.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080037#include <nativebase/nativebase.h>
Devin Moore8e506ac2023-08-25 00:13:51 +000038#include <ui/GraphicBufferMapper.h>
Wonsik Kimebe0f9e2019-07-03 11:06:51 -070039#include <ui/Fence.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080040
41#include <C2AllocatorGralloc.h>
42#include <C2BlockInternal.h>
43#include <C2Debug.h>
44
45#include "Codec2Buffer.h"
Wonsik Kim3ce32b12024-08-14 00:17:48 +000046#include "Codec2BufferUtils.h"
Pawin Vongmasa36653902018-11-15 00:10:25 -080047
48namespace android {
49
50// Codec2Buffer
51
52bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const {
53 if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
54 return false;
55 }
56 if (!buffer) {
57 // Nothing to copy, so we can copy by doing nothing.
58 return true;
59 }
60 if (buffer->data().type() != C2BufferData::LINEAR) {
61 return false;
62 }
63 if (buffer->data().linearBlocks().size() == 0u) {
64 // Nothing to copy, so we can copy by doing nothing.
65 return true;
66 } else if (buffer->data().linearBlocks().size() > 1u) {
67 // We don't know how to copy more than one blocks.
68 return false;
69 }
70 if (buffer->data().linearBlocks()[0].size() > capacity()) {
71 // It won't fit.
72 return false;
73 }
74 return true;
75}
76
77bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
78 // We assume that all canCopyLinear() checks passed.
79 if (!buffer || buffer->data().linearBlocks().size() == 0u
80 || buffer->data().linearBlocks()[0].size() == 0u) {
81 setRange(0, 0);
82 return true;
83 }
84 C2ReadView view = buffer->data().linearBlocks()[0].map().get();
85 if (view.error() != C2_OK) {
86 ALOGD("Error while mapping: %d", view.error());
87 return false;
88 }
89 if (view.capacity() > capacity()) {
90 ALOGD("C2ConstLinearBlock lied --- it actually doesn't fit: view(%u) > this(%zu)",
91 view.capacity(), capacity());
92 return false;
93 }
94 memcpy(base(), view.data(), view.capacity());
95 setRange(0, view.capacity());
96 return true;
97}
98
99void Codec2Buffer::setImageData(const sp<ABuffer> &imageData) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -0800100 mImageData = imageData;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800101}
102
103// LocalLinearBuffer
104
105bool LocalLinearBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
106 return canCopyLinear(buffer);
107}
108
109bool LocalLinearBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
110 return copyLinear(buffer);
111}
112
113// DummyContainerBuffer
114
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800115static uint8_t sDummyByte[1] = { 0 };
116
Pawin Vongmasa36653902018-11-15 00:10:25 -0800117DummyContainerBuffer::DummyContainerBuffer(
118 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer)
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800119 : Codec2Buffer(format, new ABuffer(sDummyByte, 1)),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800120 mBufferRef(buffer) {
121 setRange(0, buffer ? 1 : 0);
122}
123
124std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700125 return mBufferRef;
126}
127
128void DummyContainerBuffer::clearC2BufferRefs() {
129 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800130}
131
132bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
133 return !mBufferRef;
134}
135
136bool DummyContainerBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
137 mBufferRef = buffer;
138 setRange(0, mBufferRef ? 1 : 0);
139 return true;
140}
141
142// LinearBlockBuffer
143
144// static
145sp<LinearBlockBuffer> LinearBlockBuffer::Allocate(
146 const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) {
147 C2WriteView writeView(block->map().get());
148 if (writeView.error() != C2_OK) {
149 return nullptr;
150 }
151 return new LinearBlockBuffer(format, std::move(writeView), block);
152}
153
154std::shared_ptr<C2Buffer> LinearBlockBuffer::asC2Buffer() {
155 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
156}
157
158bool LinearBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
159 return canCopyLinear(buffer);
160}
161
162bool LinearBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
163 return copyLinear(buffer);
164}
165
166LinearBlockBuffer::LinearBlockBuffer(
167 const sp<AMessage> &format,
168 C2WriteView&& writeView,
169 const std::shared_ptr<C2LinearBlock> &block)
170 : Codec2Buffer(format, new ABuffer(writeView.data(), writeView.size())),
171 mWriteView(writeView),
172 mBlock(block) {
173}
174
175// ConstLinearBlockBuffer
176
177// static
178sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::Allocate(
179 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) {
180 if (!buffer
181 || buffer->data().type() != C2BufferData::LINEAR
182 || buffer->data().linearBlocks().size() != 1u) {
Wonsik Kim68af8e52024-04-11 17:57:57 +0000183 if (!buffer) {
184 ALOGD("ConstLinearBlockBuffer::Allocate: null buffer");
185 } else {
186 ALOGW("ConstLinearBlockBuffer::Allocate: type=%d # linear blocks=%zu",
187 buffer->data().type(), buffer->data().linearBlocks().size());
188 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800189 return nullptr;
190 }
191 C2ReadView readView(buffer->data().linearBlocks()[0].map().get());
192 if (readView.error() != C2_OK) {
Wonsik Kim68af8e52024-04-11 17:57:57 +0000193 ALOGW("ConstLinearBlockBuffer::Allocate: readView.error()=%d", readView.error());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800194 return nullptr;
195 }
196 return new ConstLinearBlockBuffer(format, std::move(readView), buffer);
197}
198
199ConstLinearBlockBuffer::ConstLinearBlockBuffer(
200 const sp<AMessage> &format,
201 C2ReadView&& readView,
202 const std::shared_ptr<C2Buffer> &buffer)
203 : Codec2Buffer(format, new ABuffer(
204 // NOTE: ABuffer only takes non-const pointer but this data is
205 // supposed to be read-only.
206 const_cast<uint8_t *>(readView.data()), readView.capacity())),
207 mReadView(readView),
208 mBufferRef(buffer) {
209}
210
211std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700212 return mBufferRef;
213}
214
215void ConstLinearBlockBuffer::clearC2BufferRefs() {
216 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800217}
218
Pawin Vongmasa36653902018-11-15 00:10:25 -0800219// GraphicBlockBuffer
220
221// static
222sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
223 const sp<AMessage> &format,
224 const std::shared_ptr<C2GraphicBlock> &block,
225 std::function<sp<ABuffer>(size_t)> alloc) {
My Name6bd9a7d2022-03-25 12:37:58 -0700226 ATRACE_BEGIN("GraphicBlockBuffer::Allocate block->map()");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800227 C2GraphicView view(block->map().get());
My Name6bd9a7d2022-03-25 12:37:58 -0700228 ATRACE_END();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800229 if (view.error() != C2_OK) {
230 ALOGD("C2GraphicBlock::map failed: %d", view.error());
231 return nullptr;
232 }
233
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700234 GraphicView2MediaImageConverter converter(view, format, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800235 if (converter.initCheck() != OK) {
236 ALOGD("Converter init failed: %d", converter.initCheck());
237 return nullptr;
238 }
239 bool wrapped = true;
240 sp<ABuffer> buffer = converter.wrap();
241 if (buffer == nullptr) {
242 buffer = alloc(converter.backBufferSize());
243 if (!converter.setBackBuffer(buffer)) {
244 ALOGD("Converter failed to set back buffer");
245 return nullptr;
246 }
247 wrapped = false;
248 }
249 return new GraphicBlockBuffer(
250 format,
251 buffer,
252 std::move(view),
253 block,
254 converter.imageData(),
255 wrapped);
256}
257
258GraphicBlockBuffer::GraphicBlockBuffer(
259 const sp<AMessage> &format,
260 const sp<ABuffer> &buffer,
261 C2GraphicView &&view,
262 const std::shared_ptr<C2GraphicBlock> &block,
263 const sp<ABuffer> &imageData,
264 bool wrapped)
265 : Codec2Buffer(format, buffer),
266 mView(view),
267 mBlock(block),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800268 mWrapped(wrapped) {
269 setImageData(imageData);
270}
271
272std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
My Name6bd9a7d2022-03-25 12:37:58 -0700273 ATRACE_CALL();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800274 uint32_t width = mView.width();
275 uint32_t height = mView.height();
276 if (!mWrapped) {
277 (void)ImageCopy(mView, base(), imageData());
278 }
279 return C2Buffer::CreateGraphicBuffer(
280 mBlock->share(C2Rect(width, height), C2Fence()));
281}
282
283// GraphicMetadataBuffer
284GraphicMetadataBuffer::GraphicMetadataBuffer(
285 const sp<AMessage> &format,
286 const std::shared_ptr<C2Allocator> &alloc)
287 : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))),
288 mAlloc(alloc) {
289 ((VideoNativeMetadata *)base())->pBuffer = nullptr;
290}
291
292std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
bohua222c0b2021-01-12 18:54:53 -0800293#ifdef __LP64__
294 static std::once_flag s_checkOnce;
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700295 static bool s_is64bitOk {true};
bohua222c0b2021-01-12 18:54:53 -0800296 std::call_once(s_checkOnce, [&](){
297 const std::string abi32list =
298 ::android::base::GetProperty("ro.product.cpu.abilist32", "");
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700299 if (!abi32list.empty()) {
300 int32_t inputSurfaceSetting =
301 ::android::base::GetIntProperty("debug.stagefright.c2inputsurface", int32_t(0));
302 s_is64bitOk = inputSurfaceSetting != 0;
bohua222c0b2021-01-12 18:54:53 -0800303 }
304 });
305
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700306 if (!s_is64bitOk) {
307 ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object"\
308 "when debug.stagefright.c2inputsurface is set to 0");
bohua222c0b2021-01-12 18:54:53 -0800309 return nullptr;
310 }
311#endif
312
Pawin Vongmasa36653902018-11-15 00:10:25 -0800313 VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
314 ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
315 if (buffer == nullptr) {
316 ALOGD("VideoNativeMetadata contains null buffer");
317 return nullptr;
318 }
319
320 ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height);
321 C2Handle *handle = WrapNativeCodec2GrallocHandle(
Sungtak Leea4d13be2019-01-23 15:24:46 -0800322 buffer->handle,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800323 buffer->width,
324 buffer->height,
325 buffer->format,
326 buffer->usage,
327 buffer->stride);
328 std::shared_ptr<C2GraphicAllocation> alloc;
329 c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc);
330 if (err != C2_OK) {
331 ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation");
Chih-Yu Huangc0ac3552021-03-11 14:37:10 +0900332 native_handle_close(handle);
333 native_handle_delete(handle);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800334 return nullptr;
335 }
336 std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
337
338 meta->pBuffer = 0;
Wonsik Kimebe0f9e2019-07-03 11:06:51 -0700339 // TODO: wrap this in C2Fence so that the component can wait when it
340 // actually starts processing.
341 if (meta->nFenceFd >= 0) {
342 sp<Fence> fence(new Fence(meta->nFenceFd));
343 fence->waitForever(LOG_TAG);
344 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800345 return C2Buffer::CreateGraphicBuffer(
346 block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800347}
348
349// ConstGraphicBlockBuffer
350
351// static
352sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
353 const sp<AMessage> &format,
354 const std::shared_ptr<C2Buffer> &buffer,
355 std::function<sp<ABuffer>(size_t)> alloc) {
356 if (!buffer
357 || buffer->data().type() != C2BufferData::GRAPHIC
358 || buffer->data().graphicBlocks().size() != 1u) {
359 ALOGD("C2Buffer precond fail");
360 return nullptr;
361 }
My Name6bd9a7d2022-03-25 12:37:58 -0700362 ATRACE_BEGIN("ConstGraphicBlockBuffer::Allocate block->map()");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800363 std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
364 buffer->data().graphicBlocks()[0].map().get()));
My Name6bd9a7d2022-03-25 12:37:58 -0700365 ATRACE_END();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800366 std::unique_ptr<const C2GraphicView> holder;
367
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700368 GraphicView2MediaImageConverter converter(*view, format, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800369 if (converter.initCheck() != OK) {
370 ALOGD("Converter init failed: %d", converter.initCheck());
371 return nullptr;
372 }
373 bool wrapped = true;
374 sp<ABuffer> aBuffer = converter.wrap();
375 if (aBuffer == nullptr) {
376 aBuffer = alloc(converter.backBufferSize());
377 if (!converter.setBackBuffer(aBuffer)) {
378 ALOGD("Converter failed to set back buffer");
379 return nullptr;
380 }
381 wrapped = false;
382 converter.copyToMediaImage();
383 // We don't need the view.
384 holder = std::move(view);
385 }
386 return new ConstGraphicBlockBuffer(
387 format,
388 aBuffer,
389 std::move(view),
390 buffer,
391 converter.imageData(),
392 wrapped);
393}
394
395// static
396sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
397 const sp<AMessage> &format,
398 std::function<sp<ABuffer>(size_t)> alloc) {
399 int32_t width, height;
400 if (!format->findInt32("width", &width)
401 || !format->findInt32("height", &height)) {
402 ALOGD("format had no width / height");
403 return nullptr;
404 }
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700405 int32_t colorFormat = COLOR_FormatYUV420Flexible;
406 int32_t bpp = 12; // 8(Y) + 2(U) + 2(V)
407 if (format->findInt32(KEY_COLOR_FORMAT, &colorFormat)) {
408 if (colorFormat == COLOR_FormatYUVP010) {
409 bpp = 24; // 16(Y) + 4(U) + 4(V)
410 }
411 }
412 sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * bpp / 8));
Jiajia Cong9ed0ab22020-12-02 12:00:49 +0800413 if (aBuffer == nullptr) {
414 ALOGD("%s: failed to allocate buffer", __func__);
415 return nullptr;
416 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800417 return new ConstGraphicBlockBuffer(
418 format,
419 aBuffer,
420 nullptr,
421 nullptr,
422 nullptr,
423 false);
424}
425
426ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
427 const sp<AMessage> &format,
428 const sp<ABuffer> &aBuffer,
429 std::unique_ptr<const C2GraphicView> &&view,
430 const std::shared_ptr<C2Buffer> &buffer,
431 const sp<ABuffer> &imageData,
432 bool wrapped)
433 : Codec2Buffer(format, aBuffer),
434 mView(std::move(view)),
435 mBufferRef(buffer),
436 mWrapped(wrapped) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -0800437 setImageData(imageData);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800438}
439
440std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700441 return mBufferRef;
442}
443
444void ConstGraphicBlockBuffer::clearC2BufferRefs() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800445 mView.reset();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700446 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800447}
448
449bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
450 if (mWrapped || mBufferRef) {
451 ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
452 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
453 return false;
454 }
455 if (!buffer) {
456 // Nothing to copy, so we can copy by doing nothing.
457 return true;
458 }
459 if (buffer->data().type() != C2BufferData::GRAPHIC) {
460 ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
461 return false;
462 }
463 if (buffer->data().graphicBlocks().size() == 0) {
464 return true;
465 } else if (buffer->data().graphicBlocks().size() != 1u) {
466 ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
467 return false;
468 }
469
My Name6bd9a7d2022-03-25 12:37:58 -0700470 ATRACE_BEGIN("ConstGraphicBlockBuffer::canCopy block->map()");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800471 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700472 buffer->data().graphicBlocks()[0].map().get(),
473 // FIXME: format() is not const, but we cannot change it, so do a const cast here
474 const_cast<ConstGraphicBlockBuffer *>(this)->format(),
475 true /* copy */);
My Name6bd9a7d2022-03-25 12:37:58 -0700476 ATRACE_END();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800477 if (converter.initCheck() != OK) {
478 ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
479 return false;
480 }
481 if (converter.backBufferSize() > capacity()) {
482 ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
483 converter.backBufferSize(), capacity());
484 return false;
485 }
486 return true;
487}
488
489bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
490 if (!buffer || buffer->data().graphicBlocks().size() == 0) {
491 setRange(0, 0);
492 return true;
493 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800494
495 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700496 buffer->data().graphicBlocks()[0].map().get(), format(), true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800497 if (converter.initCheck() != OK) {
498 ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
499 return false;
500 }
501 sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
502 if (!converter.setBackBuffer(aBuffer)) {
503 ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
504 return false;
505 }
Pin-chih Lin1971e2c2019-04-15 19:36:26 +0800506 setRange(0, aBuffer->size()); // align size info
Pawin Vongmasa36653902018-11-15 00:10:25 -0800507 converter.copyToMediaImage();
508 setImageData(converter.imageData());
509 mBufferRef = buffer;
510 return true;
511}
512
513// EncryptedLinearBlockBuffer
514
515EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
516 const sp<AMessage> &format,
517 const std::shared_ptr<C2LinearBlock> &block,
518 const sp<IMemory> &memory,
519 int32_t heapSeqNum)
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700520 // TODO: Using unsecurePointer() has some associated security pitfalls
521 // (see declaration for details).
522 // Either document why it is safe in this case or address the
523 // issue (e.g. by copying).
524 : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800525 mBlock(block),
526 mMemory(memory),
527 mHeapSeqNum(heapSeqNum) {
528}
529
530std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
531 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
532}
533
534void EncryptedLinearBlockBuffer::fillSourceBuffer(
Robert Shih895fba92019-07-16 16:29:44 -0700535 hardware::drm::V1_0::SharedBuffer *source) {
536 BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800537}
538
539void EncryptedLinearBlockBuffer::fillSourceBuffer(
540 hardware::cas::native::V1_0::SharedBuffer *source) {
541 ssize_t offset;
542 size_t size;
543
544 mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
545 source->heapBase = *mHidlMemory;
546 source->offset = offset;
547 source->size = size;
548}
549
550bool EncryptedLinearBlockBuffer::copyDecryptedContent(
551 const sp<IMemory> &decrypted, size_t length) {
552 C2WriteView view = mBlock->map().get();
553 if (view.error() != C2_OK) {
554 return false;
555 }
556 if (view.size() < length) {
557 return false;
558 }
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700559 memcpy(view.data(), decrypted->unsecurePointer(), length);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800560 return true;
561}
562
563bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
564 return copyDecryptedContent(mMemory, length);
565}
566
567native_handle_t *EncryptedLinearBlockBuffer::handle() const {
568 return const_cast<native_handle_t *>(mBlock->handle());
569}
570
Arun Johnson564f3a92024-02-01 19:09:45 +0000571void EncryptedLinearBlockBuffer::getMappedBlock(
572 std::unique_ptr<MappedBlock> * const mappedBlock) const {
573 if (mappedBlock) {
574 mappedBlock->reset(new EncryptedLinearBlockBuffer::MappedBlock(mBlock));
575 }
576 return;
577}
578
579EncryptedLinearBlockBuffer::MappedBlock::MappedBlock(
580 const std::shared_ptr<C2LinearBlock> &block) : mView(block->map().get()) {
581}
582
583bool EncryptedLinearBlockBuffer::MappedBlock::copyDecryptedContent(
584 const sp<IMemory> &decrypted, size_t length) {
585 if (mView.error() != C2_OK) {
586 return false;
587 }
588 if (mView.size() < length) {
589 ALOGE("View size(%d) less than decrypted length(%zu)",
590 mView.size(), length);
591 return false;
592 }
593 memcpy(mView.data(), decrypted->unsecurePointer(), length);
594 mView.setOffset(mView.offset() + length);
595 return true;
596}
597
598EncryptedLinearBlockBuffer::MappedBlock::~MappedBlock() {
599 mView.setOffset(0);
600}
601
Wonsik Kima79c5522022-01-18 16:29:24 -0800602using ::aidl::android::hardware::graphics::common::Cta861_3;
603using ::aidl::android::hardware::graphics::common::Smpte2086;
604
Wonsik Kima79c5522022-01-18 16:29:24 -0800605namespace {
606
Devin Moore8e506ac2023-08-25 00:13:51 +0000607class GrallocBuffer {
Wonsik Kima79c5522022-01-18 16:29:24 -0800608public:
Devin Moore8e506ac2023-08-25 00:13:51 +0000609 GrallocBuffer(const C2Handle *const handle) : mBuffer(nullptr) {
610 GraphicBufferMapper& mapper = GraphicBufferMapper::get();
611
Wonsik Kime2aa2402022-04-08 14:07:14 -0700612 // Unwrap raw buffer handle from the C2Handle
613 native_handle_t *nh = UnwrapNativeCodec2GrallocHandle(handle);
614 if (!nh) {
Sungtak Lee16204722024-02-07 22:26:19 +0000615 ALOGE("handle is not compatible to any gralloc C2Handle types");
616 return;
Wonsik Kime2aa2402022-04-08 14:07:14 -0700617 }
618 // Import the raw handle so IMapper can use the buffer. The imported
619 // handle must be freed when the client is done with the buffer.
Devin Moore8e506ac2023-08-25 00:13:51 +0000620 status_t status = mapper.importBufferNoValidate(
621 nh,
622 &mBuffer);
623
624 if (status != OK) {
625 ALOGE("Failed to import buffer. Status: %d.", status);
626 return;
627 }
Wonsik Kime2aa2402022-04-08 14:07:14 -0700628
629 // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
630 // does not clone the fds. Thus we need to delete the handle
631 // without closing it.
632 native_handle_delete(nh);
633 }
634
Devin Moore8e506ac2023-08-25 00:13:51 +0000635 ~GrallocBuffer() {
636 GraphicBufferMapper& mapper = GraphicBufferMapper::get();
637 if (mBuffer) {
Wonsik Kime2aa2402022-04-08 14:07:14 -0700638 // Free the imported buffer handle. This does not release the
639 // underlying buffer itself.
Devin Moore8e506ac2023-08-25 00:13:51 +0000640 mapper.freeBuffer(mBuffer);
Wonsik Kima79c5522022-01-18 16:29:24 -0800641 }
642 }
Wonsik Kime2aa2402022-04-08 14:07:14 -0700643
Devin Moore8e506ac2023-08-25 00:13:51 +0000644 buffer_handle_t get() const { return mBuffer; }
Wonsik Kime2aa2402022-04-08 14:07:14 -0700645 operator bool() const { return (mBuffer != nullptr); }
Wonsik Kima79c5522022-01-18 16:29:24 -0800646private:
Devin Moore8e506ac2023-08-25 00:13:51 +0000647 buffer_handle_t mBuffer;
Wonsik Kima79c5522022-01-18 16:29:24 -0800648};
649
650} // namspace
651
652c2_status_t GetHdrMetadataFromGralloc4Handle(
653 const C2Handle *const handle,
654 std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
655 std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
656 c2_status_t err = C2_OK;
Devin Moore8e506ac2023-08-25 00:13:51 +0000657 GraphicBufferMapper& mapper = GraphicBufferMapper::get();
658 GrallocBuffer buffer(handle);
659 if (!buffer) {
Wonsik Kima79c5522022-01-18 16:29:24 -0800660 // Gralloc4 not supported; nothing to do
661 return err;
662 }
Wonsik Kima79c5522022-01-18 16:29:24 -0800663 if (staticInfo) {
Devin Moore8e506ac2023-08-25 00:13:51 +0000664 ALOGV("Grabbing static HDR info from gralloc metadata");
Wonsik Kima79c5522022-01-18 16:29:24 -0800665 staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
666 memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
667 (*staticInfo)->maxCll = 0;
668 (*staticInfo)->maxFall = 0;
Wonsik Kima79c5522022-01-18 16:29:24 -0800669
Devin Moore8e506ac2023-08-25 00:13:51 +0000670 std::optional<Smpte2086> smpte2086;
671 status_t status = mapper.getSmpte2086(buffer.get(), &smpte2086);
Yanqiang Fan4f4e19b2024-03-07 15:18:36 +0800672 if (status != OK || !smpte2086) {
Devin Moore8e506ac2023-08-25 00:13:51 +0000673 err = C2_CORRUPTED;
674 } else {
Wonsik Kima79c5522022-01-18 16:29:24 -0800675 if (smpte2086) {
Devin Moore8e506ac2023-08-25 00:13:51 +0000676 (*staticInfo)->mastering.red.x = smpte2086->primaryRed.x;
677 (*staticInfo)->mastering.red.y = smpte2086->primaryRed.y;
678 (*staticInfo)->mastering.green.x = smpte2086->primaryGreen.x;
679 (*staticInfo)->mastering.green.y = smpte2086->primaryGreen.y;
680 (*staticInfo)->mastering.blue.x = smpte2086->primaryBlue.x;
681 (*staticInfo)->mastering.blue.y = smpte2086->primaryBlue.y;
682 (*staticInfo)->mastering.white.x = smpte2086->whitePoint.x;
683 (*staticInfo)->mastering.white.y = smpte2086->whitePoint.y;
Wonsik Kima79c5522022-01-18 16:29:24 -0800684
Devin Moore8e506ac2023-08-25 00:13:51 +0000685 (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
686 (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
Wonsik Kima79c5522022-01-18 16:29:24 -0800687 }
Wonsik Kima79c5522022-01-18 16:29:24 -0800688 }
Wonsik Kima79c5522022-01-18 16:29:24 -0800689
Devin Moore8e506ac2023-08-25 00:13:51 +0000690 std::optional<Cta861_3> cta861_3;
691 status = mapper.getCta861_3(buffer.get(), &cta861_3);
Yanqiang Fan4f4e19b2024-03-07 15:18:36 +0800692 if (status != OK || !cta861_3) {
Wonsik Kima79c5522022-01-18 16:29:24 -0800693 err = C2_CORRUPTED;
Devin Moore8e506ac2023-08-25 00:13:51 +0000694 } else {
695 if (cta861_3) {
696 (*staticInfo)->maxCll = cta861_3->maxContentLightLevel;
697 (*staticInfo)->maxFall = cta861_3->maxFrameAverageLightLevel;
698 }
Wonsik Kima79c5522022-01-18 16:29:24 -0800699 }
700 }
Jongchan Choibd2ced72023-06-26 19:36:11 +0000701
702 if (err != C2_OK) {
703 staticInfo->reset();
704 }
705
Wonsik Kima79c5522022-01-18 16:29:24 -0800706 if (dynamicInfo) {
Devin Moore8e506ac2023-08-25 00:13:51 +0000707 ALOGV("Grabbing dynamic HDR info from gralloc metadata");
Wonsik Kima79c5522022-01-18 16:29:24 -0800708 dynamicInfo->reset();
Devin Moore8e506ac2023-08-25 00:13:51 +0000709 std::optional<std::vector<uint8_t>> vec;
710 status_t status = mapper.getSmpte2094_40(buffer.get(), &vec);
Yanqiang Fan4f4e19b2024-03-07 15:18:36 +0800711 if (status != OK || !vec) {
Wonsik Kima79c5522022-01-18 16:29:24 -0800712 dynamicInfo->reset();
Devin Moore8e506ac2023-08-25 00:13:51 +0000713 err = C2_CORRUPTED;
714 } else {
715 if (vec) {
716 *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
717 vec->size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
718 memcpy((*dynamicInfo)->m.data, vec->data(), vec->size());
719 }
Wonsik Kima79c5522022-01-18 16:29:24 -0800720 }
721 }
722
723 return err;
724}
725
Hongguangfc1478a2022-07-20 22:56:06 -0700726c2_status_t SetMetadataToGralloc4Handle(
727 android_dataspace_t dataSpace,
Wonsik Kima79c5522022-01-18 16:29:24 -0800728 const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
729 const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
730 const C2Handle *const handle) {
731 c2_status_t err = C2_OK;
Devin Moore8e506ac2023-08-25 00:13:51 +0000732 GraphicBufferMapper& mapper = GraphicBufferMapper::get();
733 GrallocBuffer buffer(handle);
734 if (!buffer) {
Wonsik Kima79c5522022-01-18 16:29:24 -0800735 // Gralloc4 not supported; nothing to do
736 return err;
737 }
Devin Moore8e506ac2023-08-25 00:13:51 +0000738 status_t status = mapper.setDataspace(buffer.get(), static_cast<ui::Dataspace>(dataSpace));
739 if (status != OK) {
740 err = C2_CORRUPTED;
Hongguangfc1478a2022-07-20 22:56:06 -0700741 }
Wonsik Kima79c5522022-01-18 16:29:24 -0800742 if (staticInfo && *staticInfo) {
Devin Moore8e506ac2023-08-25 00:13:51 +0000743 ALOGV("Setting static HDR info as gralloc metadata");
Wonsik Kima79c5522022-01-18 16:29:24 -0800744 std::optional<Smpte2086> smpte2086 = Smpte2086{
745 {staticInfo->mastering.red.x, staticInfo->mastering.red.y},
746 {staticInfo->mastering.green.x, staticInfo->mastering.green.y},
747 {staticInfo->mastering.blue.x, staticInfo->mastering.blue.y},
748 {staticInfo->mastering.white.x, staticInfo->mastering.white.y},
749 staticInfo->mastering.maxLuminance,
750 staticInfo->mastering.minLuminance,
751 };
Wonsik Kime2aa2402022-04-08 14:07:14 -0700752 if (0.0 <= smpte2086->primaryRed.x && smpte2086->primaryRed.x <= 1.0
753 && 0.0 <= smpte2086->primaryRed.y && smpte2086->primaryRed.y <= 1.0
754 && 0.0 <= smpte2086->primaryGreen.x && smpte2086->primaryGreen.x <= 1.0
755 && 0.0 <= smpte2086->primaryGreen.y && smpte2086->primaryGreen.y <= 1.0
756 && 0.0 <= smpte2086->primaryBlue.x && smpte2086->primaryBlue.x <= 1.0
757 && 0.0 <= smpte2086->primaryBlue.y && smpte2086->primaryBlue.y <= 1.0
758 && 0.0 <= smpte2086->whitePoint.x && smpte2086->whitePoint.x <= 1.0
759 && 0.0 <= smpte2086->whitePoint.y && smpte2086->whitePoint.y <= 1.0
Devin Moore8e506ac2023-08-25 00:13:51 +0000760 && 0.0 <= smpte2086->maxLuminance && 0.0 <= smpte2086->minLuminance) {
761 status = mapper.setSmpte2086(buffer.get(), smpte2086);
762 if (status != OK) {
Wonsik Kima79c5522022-01-18 16:29:24 -0800763 err = C2_CORRUPTED;
764 }
765 }
766 std::optional<Cta861_3> cta861_3 = Cta861_3{
767 staticInfo->maxCll,
768 staticInfo->maxFall,
769 };
Devin Moore8e506ac2023-08-25 00:13:51 +0000770 if (0.0 <= cta861_3->maxContentLightLevel && 0.0 <= cta861_3->maxFrameAverageLightLevel) {
771 status = mapper.setCta861_3(buffer.get(), cta861_3);
772 if (status != OK) {
Wonsik Kima79c5522022-01-18 16:29:24 -0800773 err = C2_CORRUPTED;
774 }
775 }
776 }
Wonsik Kime2aa2402022-04-08 14:07:14 -0700777 if (dynamicInfo && *dynamicInfo && dynamicInfo->flexCount() > 0) {
Devin Moore8e506ac2023-08-25 00:13:51 +0000778 ALOGV("Setting dynamic HDR info as gralloc metadata");
779 if (dynamicInfo->m.type_ == C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40) {
780 std::optional<std::vector<uint8_t>> smpte2094_40 = std::vector<uint8_t>();
781 smpte2094_40->resize(dynamicInfo->flexCount());
782 memcpy(smpte2094_40->data(), dynamicInfo->m.data, dynamicInfo->flexCount());
Taehwan Kim3f3d1ac2022-05-12 10:40:29 +0900783
Devin Moore8e506ac2023-08-25 00:13:51 +0000784 status = mapper.setSmpte2094_40(buffer.get(), smpte2094_40);
785 if (status != OK) {
786 err = C2_CORRUPTED;
Wonsik Kima79c5522022-01-18 16:29:24 -0800787 }
788 } else {
789 err = C2_BAD_VALUE;
790 }
791 }
792
793 return err;
794}
795
Pawin Vongmasa36653902018-11-15 00:10:25 -0800796} // namespace android