blob: 7d4e8ab09a6ce55e766b003d89802db7b7de7295 [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 Kim1c867272024-09-04 20:47:54 +000023#include <android_media_codec.h>
24
Wonsik Kima79c5522022-01-18 16:29:24 -080025#include <aidl/android/hardware/graphics/common/Cta861_3.h>
26#include <aidl/android/hardware/graphics/common/Smpte2086.h>
Wonsik Kim89814312023-02-01 10:46:16 -080027#include <android-base/no_destructor.h>
bohua222c0b2021-01-12 18:54:53 -080028#include <android-base/properties.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070029#include <android/hardware/cas/native/1.0/types.h>
30#include <android/hardware/drm/1.0/types.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080031#include <hidlmemory/FrameworkUtils.h>
32#include <media/hardware/HardwareAPI.h>
Robert Shih895fba92019-07-16 16:29:44 -070033#include <media/stagefright/CodecBase.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080034#include <media/stagefright/MediaCodecConstants.h>
35#include <media/stagefright/foundation/ABuffer.h>
36#include <media/stagefright/foundation/AMessage.h>
37#include <media/stagefright/foundation/AUtils.h>
Wonsik Kim1c867272024-09-04 20:47:54 +000038#include <media/stagefright/foundation/ColorUtils.h>
Wonsik Kim41d83432020-04-27 16:40:49 -070039#include <mediadrm/ICrypto.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080040#include <nativebase/nativebase.h>
Devin Moore8e506ac2023-08-25 00:13:51 +000041#include <ui/GraphicBufferMapper.h>
Wonsik Kimebe0f9e2019-07-03 11:06:51 -070042#include <ui/Fence.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080043
44#include <C2AllocatorGralloc.h>
45#include <C2BlockInternal.h>
46#include <C2Debug.h>
47
48#include "Codec2Buffer.h"
Wonsik Kim3ce32b12024-08-14 00:17:48 +000049#include "Codec2BufferUtils.h"
Pawin Vongmasa36653902018-11-15 00:10:25 -080050
51namespace android {
52
53// Codec2Buffer
54
55bool Codec2Buffer::canCopyLinear(const std::shared_ptr<C2Buffer> &buffer) const {
56 if (const_cast<Codec2Buffer *>(this)->base() == nullptr) {
57 return false;
58 }
59 if (!buffer) {
60 // Nothing to copy, so we can copy by doing nothing.
61 return true;
62 }
63 if (buffer->data().type() != C2BufferData::LINEAR) {
64 return false;
65 }
66 if (buffer->data().linearBlocks().size() == 0u) {
67 // Nothing to copy, so we can copy by doing nothing.
68 return true;
69 } else if (buffer->data().linearBlocks().size() > 1u) {
70 // We don't know how to copy more than one blocks.
71 return false;
72 }
73 if (buffer->data().linearBlocks()[0].size() > capacity()) {
74 // It won't fit.
75 return false;
76 }
77 return true;
78}
79
80bool Codec2Buffer::copyLinear(const std::shared_ptr<C2Buffer> &buffer) {
81 // We assume that all canCopyLinear() checks passed.
82 if (!buffer || buffer->data().linearBlocks().size() == 0u
83 || buffer->data().linearBlocks()[0].size() == 0u) {
84 setRange(0, 0);
85 return true;
86 }
87 C2ReadView view = buffer->data().linearBlocks()[0].map().get();
88 if (view.error() != C2_OK) {
89 ALOGD("Error while mapping: %d", view.error());
90 return false;
91 }
92 if (view.capacity() > capacity()) {
93 ALOGD("C2ConstLinearBlock lied --- it actually doesn't fit: view(%u) > this(%zu)",
94 view.capacity(), capacity());
95 return false;
96 }
97 memcpy(base(), view.data(), view.capacity());
98 setRange(0, view.capacity());
99 return true;
100}
101
102void Codec2Buffer::setImageData(const sp<ABuffer> &imageData) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -0800103 mImageData = imageData;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800104}
105
106// LocalLinearBuffer
107
108bool LocalLinearBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
109 return canCopyLinear(buffer);
110}
111
112bool LocalLinearBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
113 return copyLinear(buffer);
114}
115
116// DummyContainerBuffer
117
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800118static uint8_t sDummyByte[1] = { 0 };
119
Pawin Vongmasa36653902018-11-15 00:10:25 -0800120DummyContainerBuffer::DummyContainerBuffer(
121 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer)
Pawin Vongmasa8be93112018-12-11 14:01:42 -0800122 : Codec2Buffer(format, new ABuffer(sDummyByte, 1)),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800123 mBufferRef(buffer) {
124 setRange(0, buffer ? 1 : 0);
125}
126
127std::shared_ptr<C2Buffer> DummyContainerBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700128 return mBufferRef;
129}
130
131void DummyContainerBuffer::clearC2BufferRefs() {
132 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800133}
134
135bool DummyContainerBuffer::canCopy(const std::shared_ptr<C2Buffer> &) const {
136 return !mBufferRef;
137}
138
139bool DummyContainerBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
140 mBufferRef = buffer;
141 setRange(0, mBufferRef ? 1 : 0);
142 return true;
143}
144
145// LinearBlockBuffer
146
147// static
148sp<LinearBlockBuffer> LinearBlockBuffer::Allocate(
149 const sp<AMessage> &format, const std::shared_ptr<C2LinearBlock> &block) {
150 C2WriteView writeView(block->map().get());
151 if (writeView.error() != C2_OK) {
152 return nullptr;
153 }
154 return new LinearBlockBuffer(format, std::move(writeView), block);
155}
156
157std::shared_ptr<C2Buffer> LinearBlockBuffer::asC2Buffer() {
158 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
159}
160
161bool LinearBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
162 return canCopyLinear(buffer);
163}
164
165bool LinearBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
166 return copyLinear(buffer);
167}
168
169LinearBlockBuffer::LinearBlockBuffer(
170 const sp<AMessage> &format,
171 C2WriteView&& writeView,
172 const std::shared_ptr<C2LinearBlock> &block)
173 : Codec2Buffer(format, new ABuffer(writeView.data(), writeView.size())),
174 mWriteView(writeView),
175 mBlock(block) {
176}
177
178// ConstLinearBlockBuffer
179
180// static
181sp<ConstLinearBlockBuffer> ConstLinearBlockBuffer::Allocate(
182 const sp<AMessage> &format, const std::shared_ptr<C2Buffer> &buffer) {
183 if (!buffer
184 || buffer->data().type() != C2BufferData::LINEAR
185 || buffer->data().linearBlocks().size() != 1u) {
Wonsik Kim68af8e52024-04-11 17:57:57 +0000186 if (!buffer) {
187 ALOGD("ConstLinearBlockBuffer::Allocate: null buffer");
188 } else {
189 ALOGW("ConstLinearBlockBuffer::Allocate: type=%d # linear blocks=%zu",
190 buffer->data().type(), buffer->data().linearBlocks().size());
191 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800192 return nullptr;
193 }
194 C2ReadView readView(buffer->data().linearBlocks()[0].map().get());
195 if (readView.error() != C2_OK) {
Wonsik Kim68af8e52024-04-11 17:57:57 +0000196 ALOGW("ConstLinearBlockBuffer::Allocate: readView.error()=%d", readView.error());
Pawin Vongmasa36653902018-11-15 00:10:25 -0800197 return nullptr;
198 }
199 return new ConstLinearBlockBuffer(format, std::move(readView), buffer);
200}
201
202ConstLinearBlockBuffer::ConstLinearBlockBuffer(
203 const sp<AMessage> &format,
204 C2ReadView&& readView,
205 const std::shared_ptr<C2Buffer> &buffer)
206 : Codec2Buffer(format, new ABuffer(
207 // NOTE: ABuffer only takes non-const pointer but this data is
208 // supposed to be read-only.
209 const_cast<uint8_t *>(readView.data()), readView.capacity())),
210 mReadView(readView),
211 mBufferRef(buffer) {
212}
213
214std::shared_ptr<C2Buffer> ConstLinearBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700215 return mBufferRef;
216}
217
218void ConstLinearBlockBuffer::clearC2BufferRefs() {
219 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800220}
221
Pawin Vongmasa36653902018-11-15 00:10:25 -0800222// GraphicBlockBuffer
223
224// static
225sp<GraphicBlockBuffer> GraphicBlockBuffer::Allocate(
226 const sp<AMessage> &format,
227 const std::shared_ptr<C2GraphicBlock> &block,
228 std::function<sp<ABuffer>(size_t)> alloc) {
My Name6bd9a7d2022-03-25 12:37:58 -0700229 ATRACE_BEGIN("GraphicBlockBuffer::Allocate block->map()");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800230 C2GraphicView view(block->map().get());
My Name6bd9a7d2022-03-25 12:37:58 -0700231 ATRACE_END();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800232 if (view.error() != C2_OK) {
233 ALOGD("C2GraphicBlock::map failed: %d", view.error());
234 return nullptr;
235 }
236
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700237 GraphicView2MediaImageConverter converter(view, format, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800238 if (converter.initCheck() != OK) {
239 ALOGD("Converter init failed: %d", converter.initCheck());
240 return nullptr;
241 }
242 bool wrapped = true;
243 sp<ABuffer> buffer = converter.wrap();
244 if (buffer == nullptr) {
245 buffer = alloc(converter.backBufferSize());
246 if (!converter.setBackBuffer(buffer)) {
247 ALOGD("Converter failed to set back buffer");
248 return nullptr;
249 }
250 wrapped = false;
251 }
252 return new GraphicBlockBuffer(
253 format,
254 buffer,
255 std::move(view),
256 block,
257 converter.imageData(),
258 wrapped);
259}
260
261GraphicBlockBuffer::GraphicBlockBuffer(
262 const sp<AMessage> &format,
263 const sp<ABuffer> &buffer,
264 C2GraphicView &&view,
265 const std::shared_ptr<C2GraphicBlock> &block,
266 const sp<ABuffer> &imageData,
267 bool wrapped)
268 : Codec2Buffer(format, buffer),
269 mView(view),
270 mBlock(block),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800271 mWrapped(wrapped) {
272 setImageData(imageData);
273}
274
275std::shared_ptr<C2Buffer> GraphicBlockBuffer::asC2Buffer() {
My Name6bd9a7d2022-03-25 12:37:58 -0700276 ATRACE_CALL();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800277 uint32_t width = mView.width();
278 uint32_t height = mView.height();
279 if (!mWrapped) {
280 (void)ImageCopy(mView, base(), imageData());
281 }
282 return C2Buffer::CreateGraphicBuffer(
283 mBlock->share(C2Rect(width, height), C2Fence()));
284}
285
286// GraphicMetadataBuffer
287GraphicMetadataBuffer::GraphicMetadataBuffer(
288 const sp<AMessage> &format,
289 const std::shared_ptr<C2Allocator> &alloc)
290 : Codec2Buffer(format, new ABuffer(sizeof(VideoNativeMetadata))),
291 mAlloc(alloc) {
292 ((VideoNativeMetadata *)base())->pBuffer = nullptr;
293}
294
295std::shared_ptr<C2Buffer> GraphicMetadataBuffer::asC2Buffer() {
bohua222c0b2021-01-12 18:54:53 -0800296#ifdef __LP64__
297 static std::once_flag s_checkOnce;
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700298 static bool s_is64bitOk {true};
bohua222c0b2021-01-12 18:54:53 -0800299 std::call_once(s_checkOnce, [&](){
300 const std::string abi32list =
301 ::android::base::GetProperty("ro.product.cpu.abilist32", "");
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700302 if (!abi32list.empty()) {
303 int32_t inputSurfaceSetting =
304 ::android::base::GetIntProperty("debug.stagefright.c2inputsurface", int32_t(0));
305 s_is64bitOk = inputSurfaceSetting != 0;
bohua222c0b2021-01-12 18:54:53 -0800306 }
307 });
308
Harish Mahendrakar731e9142021-04-21 17:20:39 -0700309 if (!s_is64bitOk) {
310 ALOGE("GraphicMetadataBuffer does not work in 32+64 system if compiled as 64-bit object"\
311 "when debug.stagefright.c2inputsurface is set to 0");
bohua222c0b2021-01-12 18:54:53 -0800312 return nullptr;
313 }
314#endif
315
Pawin Vongmasa36653902018-11-15 00:10:25 -0800316 VideoNativeMetadata *meta = (VideoNativeMetadata *)base();
317 ANativeWindowBuffer *buffer = (ANativeWindowBuffer *)meta->pBuffer;
318 if (buffer == nullptr) {
319 ALOGD("VideoNativeMetadata contains null buffer");
320 return nullptr;
321 }
322
323 ALOGV("VideoNativeMetadata: %dx%d", buffer->width, buffer->height);
324 C2Handle *handle = WrapNativeCodec2GrallocHandle(
Sungtak Leea4d13be2019-01-23 15:24:46 -0800325 buffer->handle,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800326 buffer->width,
327 buffer->height,
328 buffer->format,
329 buffer->usage,
330 buffer->stride);
331 std::shared_ptr<C2GraphicAllocation> alloc;
332 c2_status_t err = mAlloc->priorGraphicAllocation(handle, &alloc);
333 if (err != C2_OK) {
334 ALOGD("Failed to wrap VideoNativeMetadata into C2GraphicAllocation");
Chih-Yu Huangc0ac3552021-03-11 14:37:10 +0900335 native_handle_close(handle);
336 native_handle_delete(handle);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800337 return nullptr;
338 }
339 std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
340
341 meta->pBuffer = 0;
Wonsik Kimebe0f9e2019-07-03 11:06:51 -0700342 // TODO: wrap this in C2Fence so that the component can wait when it
343 // actually starts processing.
344 if (meta->nFenceFd >= 0) {
345 sp<Fence> fence(new Fence(meta->nFenceFd));
346 fence->waitForever(LOG_TAG);
347 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800348 return C2Buffer::CreateGraphicBuffer(
349 block->share(C2Rect(buffer->width, buffer->height), C2Fence()));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800350}
351
352// ConstGraphicBlockBuffer
353
354// static
355sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::Allocate(
356 const sp<AMessage> &format,
357 const std::shared_ptr<C2Buffer> &buffer,
358 std::function<sp<ABuffer>(size_t)> alloc) {
359 if (!buffer
360 || buffer->data().type() != C2BufferData::GRAPHIC
361 || buffer->data().graphicBlocks().size() != 1u) {
362 ALOGD("C2Buffer precond fail");
363 return nullptr;
364 }
My Name6bd9a7d2022-03-25 12:37:58 -0700365 ATRACE_BEGIN("ConstGraphicBlockBuffer::Allocate block->map()");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800366 std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
367 buffer->data().graphicBlocks()[0].map().get()));
My Name6bd9a7d2022-03-25 12:37:58 -0700368 ATRACE_END();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800369 std::unique_ptr<const C2GraphicView> holder;
370
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700371 GraphicView2MediaImageConverter converter(*view, format, false /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800372 if (converter.initCheck() != OK) {
373 ALOGD("Converter init failed: %d", converter.initCheck());
374 return nullptr;
375 }
376 bool wrapped = true;
377 sp<ABuffer> aBuffer = converter.wrap();
378 if (aBuffer == nullptr) {
379 aBuffer = alloc(converter.backBufferSize());
380 if (!converter.setBackBuffer(aBuffer)) {
381 ALOGD("Converter failed to set back buffer");
382 return nullptr;
383 }
384 wrapped = false;
385 converter.copyToMediaImage();
386 // We don't need the view.
387 holder = std::move(view);
388 }
389 return new ConstGraphicBlockBuffer(
390 format,
391 aBuffer,
392 std::move(view),
393 buffer,
394 converter.imageData(),
395 wrapped);
396}
397
398// static
399sp<ConstGraphicBlockBuffer> ConstGraphicBlockBuffer::AllocateEmpty(
400 const sp<AMessage> &format,
401 std::function<sp<ABuffer>(size_t)> alloc) {
402 int32_t width, height;
403 if (!format->findInt32("width", &width)
404 || !format->findInt32("height", &height)) {
405 ALOGD("format had no width / height");
406 return nullptr;
407 }
Wonsik Kim08a8a2b2021-05-10 19:03:47 -0700408 int32_t colorFormat = COLOR_FormatYUV420Flexible;
409 int32_t bpp = 12; // 8(Y) + 2(U) + 2(V)
410 if (format->findInt32(KEY_COLOR_FORMAT, &colorFormat)) {
411 if (colorFormat == COLOR_FormatYUVP010) {
412 bpp = 24; // 16(Y) + 4(U) + 4(V)
413 }
414 }
415 sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * bpp / 8));
Jiajia Cong9ed0ab22020-12-02 12:00:49 +0800416 if (aBuffer == nullptr) {
417 ALOGD("%s: failed to allocate buffer", __func__);
418 return nullptr;
419 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800420 return new ConstGraphicBlockBuffer(
421 format,
422 aBuffer,
423 nullptr,
424 nullptr,
425 nullptr,
426 false);
427}
428
429ConstGraphicBlockBuffer::ConstGraphicBlockBuffer(
430 const sp<AMessage> &format,
431 const sp<ABuffer> &aBuffer,
432 std::unique_ptr<const C2GraphicView> &&view,
433 const std::shared_ptr<C2Buffer> &buffer,
434 const sp<ABuffer> &imageData,
435 bool wrapped)
436 : Codec2Buffer(format, aBuffer),
437 mView(std::move(view)),
438 mBufferRef(buffer),
439 mWrapped(wrapped) {
Wonsik Kimc48ddcf2019-02-11 16:16:57 -0800440 setImageData(imageData);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800441}
442
443std::shared_ptr<C2Buffer> ConstGraphicBlockBuffer::asC2Buffer() {
Wonsik Kimf9b32122020-04-02 11:30:17 -0700444 return mBufferRef;
445}
446
447void ConstGraphicBlockBuffer::clearC2BufferRefs() {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800448 mView.reset();
Wonsik Kimf9b32122020-04-02 11:30:17 -0700449 mBufferRef.reset();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800450}
451
452bool ConstGraphicBlockBuffer::canCopy(const std::shared_ptr<C2Buffer> &buffer) const {
453 if (mWrapped || mBufferRef) {
454 ALOGD("ConstGraphicBlockBuffer::canCopy: %swrapped ; buffer ref %s",
455 mWrapped ? "" : "not ", mBufferRef ? "exists" : "doesn't exist");
456 return false;
457 }
458 if (!buffer) {
459 // Nothing to copy, so we can copy by doing nothing.
460 return true;
461 }
462 if (buffer->data().type() != C2BufferData::GRAPHIC) {
463 ALOGD("ConstGraphicBlockBuffer::canCopy: buffer precondition unsatisfied");
464 return false;
465 }
466 if (buffer->data().graphicBlocks().size() == 0) {
467 return true;
468 } else if (buffer->data().graphicBlocks().size() != 1u) {
469 ALOGD("ConstGraphicBlockBuffer::canCopy: too many blocks");
470 return false;
471 }
472
My Name6bd9a7d2022-03-25 12:37:58 -0700473 ATRACE_BEGIN("ConstGraphicBlockBuffer::canCopy block->map()");
Pawin Vongmasa36653902018-11-15 00:10:25 -0800474 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700475 buffer->data().graphicBlocks()[0].map().get(),
476 // FIXME: format() is not const, but we cannot change it, so do a const cast here
477 const_cast<ConstGraphicBlockBuffer *>(this)->format(),
478 true /* copy */);
My Name6bd9a7d2022-03-25 12:37:58 -0700479 ATRACE_END();
Pawin Vongmasa36653902018-11-15 00:10:25 -0800480 if (converter.initCheck() != OK) {
481 ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
482 return false;
483 }
484 if (converter.backBufferSize() > capacity()) {
485 ALOGD("ConstGraphicBlockBuffer::canCopy: insufficient capacity: req %u has %zu",
486 converter.backBufferSize(), capacity());
487 return false;
488 }
489 return true;
490}
491
492bool ConstGraphicBlockBuffer::copy(const std::shared_ptr<C2Buffer> &buffer) {
493 if (!buffer || buffer->data().graphicBlocks().size() == 0) {
494 setRange(0, 0);
495 return true;
496 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800497
498 GraphicView2MediaImageConverter converter(
Wonsik Kimd79ee1f2020-08-27 17:41:56 -0700499 buffer->data().graphicBlocks()[0].map().get(), format(), true /* copy */);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800500 if (converter.initCheck() != OK) {
501 ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
502 return false;
503 }
504 sp<ABuffer> aBuffer = new ABuffer(base(), capacity());
505 if (!converter.setBackBuffer(aBuffer)) {
506 ALOGD("ConstGraphicBlockBuffer::copy: set back buffer failed");
507 return false;
508 }
Pin-chih Lin1971e2c2019-04-15 19:36:26 +0800509 setRange(0, aBuffer->size()); // align size info
Pawin Vongmasa36653902018-11-15 00:10:25 -0800510 converter.copyToMediaImage();
511 setImageData(converter.imageData());
512 mBufferRef = buffer;
513 return true;
514}
515
516// EncryptedLinearBlockBuffer
517
518EncryptedLinearBlockBuffer::EncryptedLinearBlockBuffer(
519 const sp<AMessage> &format,
520 const std::shared_ptr<C2LinearBlock> &block,
521 const sp<IMemory> &memory,
522 int32_t heapSeqNum)
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700523 // TODO: Using unsecurePointer() has some associated security pitfalls
524 // (see declaration for details).
525 // Either document why it is safe in this case or address the
526 // issue (e.g. by copying).
527 : Codec2Buffer(format, new ABuffer(memory->unsecurePointer(), memory->size())),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800528 mBlock(block),
529 mMemory(memory),
530 mHeapSeqNum(heapSeqNum) {
531}
532
533std::shared_ptr<C2Buffer> EncryptedLinearBlockBuffer::asC2Buffer() {
534 return C2Buffer::CreateLinearBuffer(mBlock->share(offset(), size(), C2Fence()));
535}
536
537void EncryptedLinearBlockBuffer::fillSourceBuffer(
Robert Shih895fba92019-07-16 16:29:44 -0700538 hardware::drm::V1_0::SharedBuffer *source) {
539 BufferChannelBase::IMemoryToSharedBuffer(mMemory, mHeapSeqNum, source);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800540}
541
542void EncryptedLinearBlockBuffer::fillSourceBuffer(
543 hardware::cas::native::V1_0::SharedBuffer *source) {
544 ssize_t offset;
545 size_t size;
546
547 mHidlMemory = hardware::fromHeap(mMemory->getMemory(&offset, &size));
548 source->heapBase = *mHidlMemory;
549 source->offset = offset;
550 source->size = size;
551}
552
553bool EncryptedLinearBlockBuffer::copyDecryptedContent(
554 const sp<IMemory> &decrypted, size_t length) {
555 C2WriteView view = mBlock->map().get();
556 if (view.error() != C2_OK) {
557 return false;
558 }
559 if (view.size() < length) {
560 return false;
561 }
Ytai Ben-Tsvi7dd39722019-09-05 15:14:30 -0700562 memcpy(view.data(), decrypted->unsecurePointer(), length);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800563 return true;
564}
565
566bool EncryptedLinearBlockBuffer::copyDecryptedContentFromMemory(size_t length) {
567 return copyDecryptedContent(mMemory, length);
568}
569
570native_handle_t *EncryptedLinearBlockBuffer::handle() const {
571 return const_cast<native_handle_t *>(mBlock->handle());
572}
573
Arun Johnson564f3a92024-02-01 19:09:45 +0000574void EncryptedLinearBlockBuffer::getMappedBlock(
575 std::unique_ptr<MappedBlock> * const mappedBlock) const {
576 if (mappedBlock) {
577 mappedBlock->reset(new EncryptedLinearBlockBuffer::MappedBlock(mBlock));
578 }
579 return;
580}
581
582EncryptedLinearBlockBuffer::MappedBlock::MappedBlock(
583 const std::shared_ptr<C2LinearBlock> &block) : mView(block->map().get()) {
584}
585
586bool EncryptedLinearBlockBuffer::MappedBlock::copyDecryptedContent(
587 const sp<IMemory> &decrypted, size_t length) {
588 if (mView.error() != C2_OK) {
589 return false;
590 }
591 if (mView.size() < length) {
592 ALOGE("View size(%d) less than decrypted length(%zu)",
593 mView.size(), length);
594 return false;
595 }
596 memcpy(mView.data(), decrypted->unsecurePointer(), length);
597 mView.setOffset(mView.offset() + length);
598 return true;
599}
600
601EncryptedLinearBlockBuffer::MappedBlock::~MappedBlock() {
602 mView.setOffset(0);
603}
604
Wonsik Kima79c5522022-01-18 16:29:24 -0800605using ::aidl::android::hardware::graphics::common::Cta861_3;
606using ::aidl::android::hardware::graphics::common::Smpte2086;
607
Wonsik Kima79c5522022-01-18 16:29:24 -0800608namespace {
609
Devin Moore8e506ac2023-08-25 00:13:51 +0000610class GrallocBuffer {
Wonsik Kima79c5522022-01-18 16:29:24 -0800611public:
Devin Moore8e506ac2023-08-25 00:13:51 +0000612 GrallocBuffer(const C2Handle *const handle) : mBuffer(nullptr) {
613 GraphicBufferMapper& mapper = GraphicBufferMapper::get();
614
Wonsik Kime2aa2402022-04-08 14:07:14 -0700615 // Unwrap raw buffer handle from the C2Handle
616 native_handle_t *nh = UnwrapNativeCodec2GrallocHandle(handle);
617 if (!nh) {
Sungtak Lee16204722024-02-07 22:26:19 +0000618 ALOGE("handle is not compatible to any gralloc C2Handle types");
619 return;
Wonsik Kime2aa2402022-04-08 14:07:14 -0700620 }
621 // Import the raw handle so IMapper can use the buffer. The imported
622 // handle must be freed when the client is done with the buffer.
Devin Moore8e506ac2023-08-25 00:13:51 +0000623 status_t status = mapper.importBufferNoValidate(
624 nh,
625 &mBuffer);
626
627 if (status != OK) {
628 ALOGE("Failed to import buffer. Status: %d.", status);
629 return;
630 }
Wonsik Kime2aa2402022-04-08 14:07:14 -0700631
632 // TRICKY: UnwrapNativeCodec2GrallocHandle creates a new handle but
633 // does not clone the fds. Thus we need to delete the handle
634 // without closing it.
635 native_handle_delete(nh);
636 }
637
Devin Moore8e506ac2023-08-25 00:13:51 +0000638 ~GrallocBuffer() {
639 GraphicBufferMapper& mapper = GraphicBufferMapper::get();
640 if (mBuffer) {
Wonsik Kime2aa2402022-04-08 14:07:14 -0700641 // Free the imported buffer handle. This does not release the
642 // underlying buffer itself.
Devin Moore8e506ac2023-08-25 00:13:51 +0000643 mapper.freeBuffer(mBuffer);
Wonsik Kima79c5522022-01-18 16:29:24 -0800644 }
645 }
Wonsik Kime2aa2402022-04-08 14:07:14 -0700646
Devin Moore8e506ac2023-08-25 00:13:51 +0000647 buffer_handle_t get() const { return mBuffer; }
Wonsik Kime2aa2402022-04-08 14:07:14 -0700648 operator bool() const { return (mBuffer != nullptr); }
Wonsik Kima79c5522022-01-18 16:29:24 -0800649private:
Devin Moore8e506ac2023-08-25 00:13:51 +0000650 buffer_handle_t mBuffer;
Wonsik Kima79c5522022-01-18 16:29:24 -0800651};
652
653} // namspace
654
655c2_status_t GetHdrMetadataFromGralloc4Handle(
656 const C2Handle *const handle,
657 std::shared_ptr<C2StreamHdrStaticMetadataInfo::input> *staticInfo,
658 std::shared_ptr<C2StreamHdrDynamicMetadataInfo::input> *dynamicInfo) {
659 c2_status_t err = C2_OK;
Devin Moore8e506ac2023-08-25 00:13:51 +0000660 GraphicBufferMapper& mapper = GraphicBufferMapper::get();
661 GrallocBuffer buffer(handle);
662 if (!buffer) {
Wonsik Kima79c5522022-01-18 16:29:24 -0800663 // Gralloc4 not supported; nothing to do
664 return err;
665 }
Wonsik Kima79c5522022-01-18 16:29:24 -0800666 if (staticInfo) {
Devin Moore8e506ac2023-08-25 00:13:51 +0000667 ALOGV("Grabbing static HDR info from gralloc metadata");
Wonsik Kima79c5522022-01-18 16:29:24 -0800668 staticInfo->reset(new C2StreamHdrStaticMetadataInfo::input(0u));
669 memset(&(*staticInfo)->mastering, 0, sizeof((*staticInfo)->mastering));
670 (*staticInfo)->maxCll = 0;
671 (*staticInfo)->maxFall = 0;
Wonsik Kima79c5522022-01-18 16:29:24 -0800672
Devin Moore8e506ac2023-08-25 00:13:51 +0000673 std::optional<Smpte2086> smpte2086;
674 status_t status = mapper.getSmpte2086(buffer.get(), &smpte2086);
Yanqiang Fan4f4e19b2024-03-07 15:18:36 +0800675 if (status != OK || !smpte2086) {
Devin Moore8e506ac2023-08-25 00:13:51 +0000676 err = C2_CORRUPTED;
677 } else {
Wonsik Kima79c5522022-01-18 16:29:24 -0800678 if (smpte2086) {
Devin Moore8e506ac2023-08-25 00:13:51 +0000679 (*staticInfo)->mastering.red.x = smpte2086->primaryRed.x;
680 (*staticInfo)->mastering.red.y = smpte2086->primaryRed.y;
681 (*staticInfo)->mastering.green.x = smpte2086->primaryGreen.x;
682 (*staticInfo)->mastering.green.y = smpte2086->primaryGreen.y;
683 (*staticInfo)->mastering.blue.x = smpte2086->primaryBlue.x;
684 (*staticInfo)->mastering.blue.y = smpte2086->primaryBlue.y;
685 (*staticInfo)->mastering.white.x = smpte2086->whitePoint.x;
686 (*staticInfo)->mastering.white.y = smpte2086->whitePoint.y;
Wonsik Kima79c5522022-01-18 16:29:24 -0800687
Devin Moore8e506ac2023-08-25 00:13:51 +0000688 (*staticInfo)->mastering.maxLuminance = smpte2086->maxLuminance;
689 (*staticInfo)->mastering.minLuminance = smpte2086->minLuminance;
Wonsik Kima79c5522022-01-18 16:29:24 -0800690 }
Wonsik Kima79c5522022-01-18 16:29:24 -0800691 }
Wonsik Kima79c5522022-01-18 16:29:24 -0800692
Devin Moore8e506ac2023-08-25 00:13:51 +0000693 std::optional<Cta861_3> cta861_3;
694 status = mapper.getCta861_3(buffer.get(), &cta861_3);
Yanqiang Fan4f4e19b2024-03-07 15:18:36 +0800695 if (status != OK || !cta861_3) {
Wonsik Kima79c5522022-01-18 16:29:24 -0800696 err = C2_CORRUPTED;
Devin Moore8e506ac2023-08-25 00:13:51 +0000697 } else {
698 if (cta861_3) {
699 (*staticInfo)->maxCll = cta861_3->maxContentLightLevel;
700 (*staticInfo)->maxFall = cta861_3->maxFrameAverageLightLevel;
701 }
Wonsik Kima79c5522022-01-18 16:29:24 -0800702 }
703 }
Jongchan Choibd2ced72023-06-26 19:36:11 +0000704
705 if (err != C2_OK) {
706 staticInfo->reset();
707 }
708
Wonsik Kima79c5522022-01-18 16:29:24 -0800709 if (dynamicInfo) {
Devin Moore8e506ac2023-08-25 00:13:51 +0000710 ALOGV("Grabbing dynamic HDR info from gralloc metadata");
Wonsik Kima79c5522022-01-18 16:29:24 -0800711 dynamicInfo->reset();
Devin Moore8e506ac2023-08-25 00:13:51 +0000712 std::optional<std::vector<uint8_t>> vec;
713 status_t status = mapper.getSmpte2094_40(buffer.get(), &vec);
Yanqiang Fan4f4e19b2024-03-07 15:18:36 +0800714 if (status != OK || !vec) {
Wonsik Kima79c5522022-01-18 16:29:24 -0800715 dynamicInfo->reset();
Devin Moore8e506ac2023-08-25 00:13:51 +0000716 err = C2_CORRUPTED;
717 } else {
718 if (vec) {
719 *dynamicInfo = C2StreamHdrDynamicMetadataInfo::input::AllocShared(
720 vec->size(), 0u, C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40);
721 memcpy((*dynamicInfo)->m.data, vec->data(), vec->size());
722 }
Wonsik Kima79c5522022-01-18 16:29:24 -0800723 }
724 }
725
726 return err;
727}
728
Hongguangfc1478a2022-07-20 22:56:06 -0700729c2_status_t SetMetadataToGralloc4Handle(
730 android_dataspace_t dataSpace,
Wonsik Kima79c5522022-01-18 16:29:24 -0800731 const std::shared_ptr<const C2StreamHdrStaticMetadataInfo::output> &staticInfo,
732 const std::shared_ptr<const C2StreamHdrDynamicMetadataInfo::output> &dynamicInfo,
733 const C2Handle *const handle) {
734 c2_status_t err = C2_OK;
Devin Moore8e506ac2023-08-25 00:13:51 +0000735 GraphicBufferMapper& mapper = GraphicBufferMapper::get();
736 GrallocBuffer buffer(handle);
737 if (!buffer) {
Wonsik Kima79c5522022-01-18 16:29:24 -0800738 // Gralloc4 not supported; nothing to do
739 return err;
740 }
Wonsik Kim1c867272024-09-04 20:47:54 +0000741 // Use V0 dataspaces for Gralloc4+
742 if (android::media::codec::provider_->dataspace_v0_partial()) {
743 ColorUtils::convertDataSpaceToV0(dataSpace);
744 }
Devin Moore8e506ac2023-08-25 00:13:51 +0000745 status_t status = mapper.setDataspace(buffer.get(), static_cast<ui::Dataspace>(dataSpace));
746 if (status != OK) {
747 err = C2_CORRUPTED;
Hongguangfc1478a2022-07-20 22:56:06 -0700748 }
Wonsik Kima79c5522022-01-18 16:29:24 -0800749 if (staticInfo && *staticInfo) {
Devin Moore8e506ac2023-08-25 00:13:51 +0000750 ALOGV("Setting static HDR info as gralloc metadata");
Wonsik Kima79c5522022-01-18 16:29:24 -0800751 std::optional<Smpte2086> smpte2086 = Smpte2086{
752 {staticInfo->mastering.red.x, staticInfo->mastering.red.y},
753 {staticInfo->mastering.green.x, staticInfo->mastering.green.y},
754 {staticInfo->mastering.blue.x, staticInfo->mastering.blue.y},
755 {staticInfo->mastering.white.x, staticInfo->mastering.white.y},
756 staticInfo->mastering.maxLuminance,
757 staticInfo->mastering.minLuminance,
758 };
Wonsik Kime2aa2402022-04-08 14:07:14 -0700759 if (0.0 <= smpte2086->primaryRed.x && smpte2086->primaryRed.x <= 1.0
760 && 0.0 <= smpte2086->primaryRed.y && smpte2086->primaryRed.y <= 1.0
761 && 0.0 <= smpte2086->primaryGreen.x && smpte2086->primaryGreen.x <= 1.0
762 && 0.0 <= smpte2086->primaryGreen.y && smpte2086->primaryGreen.y <= 1.0
763 && 0.0 <= smpte2086->primaryBlue.x && smpte2086->primaryBlue.x <= 1.0
764 && 0.0 <= smpte2086->primaryBlue.y && smpte2086->primaryBlue.y <= 1.0
765 && 0.0 <= smpte2086->whitePoint.x && smpte2086->whitePoint.x <= 1.0
766 && 0.0 <= smpte2086->whitePoint.y && smpte2086->whitePoint.y <= 1.0
Devin Moore8e506ac2023-08-25 00:13:51 +0000767 && 0.0 <= smpte2086->maxLuminance && 0.0 <= smpte2086->minLuminance) {
768 status = mapper.setSmpte2086(buffer.get(), smpte2086);
769 if (status != OK) {
Wonsik Kima79c5522022-01-18 16:29:24 -0800770 err = C2_CORRUPTED;
771 }
772 }
773 std::optional<Cta861_3> cta861_3 = Cta861_3{
774 staticInfo->maxCll,
775 staticInfo->maxFall,
776 };
Devin Moore8e506ac2023-08-25 00:13:51 +0000777 if (0.0 <= cta861_3->maxContentLightLevel && 0.0 <= cta861_3->maxFrameAverageLightLevel) {
778 status = mapper.setCta861_3(buffer.get(), cta861_3);
779 if (status != OK) {
Wonsik Kima79c5522022-01-18 16:29:24 -0800780 err = C2_CORRUPTED;
781 }
782 }
783 }
Wonsik Kime2aa2402022-04-08 14:07:14 -0700784 if (dynamicInfo && *dynamicInfo && dynamicInfo->flexCount() > 0) {
Devin Moore8e506ac2023-08-25 00:13:51 +0000785 ALOGV("Setting dynamic HDR info as gralloc metadata");
786 if (dynamicInfo->m.type_ == C2Config::HDR_DYNAMIC_METADATA_TYPE_SMPTE_2094_40) {
787 std::optional<std::vector<uint8_t>> smpte2094_40 = std::vector<uint8_t>();
788 smpte2094_40->resize(dynamicInfo->flexCount());
789 memcpy(smpte2094_40->data(), dynamicInfo->m.data, dynamicInfo->flexCount());
Taehwan Kim3f3d1ac2022-05-12 10:40:29 +0900790
Devin Moore8e506ac2023-08-25 00:13:51 +0000791 status = mapper.setSmpte2094_40(buffer.get(), smpte2094_40);
792 if (status != OK) {
793 err = C2_CORRUPTED;
Wonsik Kima79c5522022-01-18 16:29:24 -0800794 }
795 } else {
796 err = C2_BAD_VALUE;
797 }
798 }
799
800 return err;
801}
802
Pawin Vongmasa36653902018-11-15 00:10:25 -0800803} // namespace android