/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "yuv.h" namespace android { namespace hardware { namespace camera { namespace provider { namespace implementation { namespace yuv { namespace { void copyCbCrPlane(uint8_t* dst, const size_t width, size_t height, const void* src, const size_t srcStride, const size_t srcStep) { const uint8_t* src8 = static_cast(src); for (; height > 0; --height, src8 += srcStride) { const uint8_t* p = src8; for (size_t rem = width & 15; rem; --rem, ++dst, p += srcStep) { *dst = *p; } for (size_t width16 = width >> 4; width16; --width16) { *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; *dst = *p; ++dst; p += srcStep; } } } } // namespace size_t NV21size(const size_t width, const size_t height) { LOG_ALWAYS_FATAL_IF((width & 1) || (height & 1)); return width * height * 3 / 2; } android_ycbcr NV21init(const size_t width, const size_t height, void* data) { LOG_ALWAYS_FATAL_IF((width & 1) || (height & 1)); uint8_t* data8 = static_cast(data); const size_t area = width * height; android_ycbcr nv21; nv21.y = data8; nv21.cb = data8 + area; nv21.cr = data8 + area + (area >> 2); nv21.ystride = width; nv21.cstride = width / 2; nv21.chroma_step = 1; return nv21; } android_ycbcr toNV21Shallow(const size_t width, const size_t height, const android_ycbcr& ycbcr, std::vector* data) { LOG_ALWAYS_FATAL_IF((width & 1) || (height & 1)); if (ycbcr.chroma_step == 1) { return ycbcr; } const size_t area = width * height; data->resize(area / 2); // only for CbCr android_ycbcr nv21; nv21.y = ycbcr.y; // don't copy Y nv21.ystride = ycbcr.ystride; nv21.cb = &data[0]; nv21.cr = &data[area / 4]; nv21.cstride = width / 2; nv21.chroma_step = 1; copyCbCrPlane(&((*data)[0]), width / 2, height / 2, ycbcr.cb, ycbcr.cstride, ycbcr.chroma_step); copyCbCrPlane(&((*data)[area / 4]), width / 2, height / 2, ycbcr.cr, ycbcr.cstride, ycbcr.chroma_step); return nv21; } } // namespace yuv } // namespace implementation } // namespace provider } // namespace camera } // namespace hardware } // namespace android