1 /*
2  * Copyright (C) 2023 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 #include <log/log.h>
18 #include "yuv.h"
19 
20 namespace android {
21 namespace hardware {
22 namespace camera {
23 namespace provider {
24 namespace implementation {
25 namespace yuv {
26 namespace {
27 
copyCbCrPlane(uint8_t * dst,const size_t width,size_t height,const void * src,const size_t srcStride,const size_t srcStep)28 void copyCbCrPlane(uint8_t* dst, const size_t width, size_t height,
29                    const void* src, const size_t srcStride, const size_t srcStep) {
30     const uint8_t* src8 = static_cast<const uint8_t*>(src);
31     for (; height > 0; --height, src8 += srcStride) {
32         const uint8_t* p = src8;
33         for (size_t rem = width & 15; rem; --rem, ++dst, p += srcStep) {
34             *dst = *p;
35         }
36 
37         for (size_t width16 = width >> 4; width16; --width16) {
38             *dst = *p; ++dst; p += srcStep;
39             *dst = *p; ++dst; p += srcStep;
40             *dst = *p; ++dst; p += srcStep;
41             *dst = *p; ++dst; p += srcStep;
42             *dst = *p; ++dst; p += srcStep;
43             *dst = *p; ++dst; p += srcStep;
44             *dst = *p; ++dst; p += srcStep;
45             *dst = *p; ++dst; p += srcStep;
46             *dst = *p; ++dst; p += srcStep;
47             *dst = *p; ++dst; p += srcStep;
48             *dst = *p; ++dst; p += srcStep;
49             *dst = *p; ++dst; p += srcStep;
50             *dst = *p; ++dst; p += srcStep;
51             *dst = *p; ++dst; p += srcStep;
52             *dst = *p; ++dst; p += srcStep;
53             *dst = *p; ++dst; p += srcStep;
54         }
55     }
56 }
57 
58 }  // namespace
59 
NV21size(const size_t width,const size_t height)60 size_t NV21size(const size_t width, const size_t height) {
61     LOG_ALWAYS_FATAL_IF((width & 1) || (height & 1));
62     return width * height * 3 / 2;
63 }
64 
NV21init(const size_t width,const size_t height,void * data)65 android_ycbcr NV21init(const size_t width, const size_t height, void* data) {
66     LOG_ALWAYS_FATAL_IF((width & 1) || (height & 1));
67     uint8_t* data8 = static_cast<uint8_t*>(data);
68     const size_t area = width * height;
69 
70     android_ycbcr nv21;
71     nv21.y = data8;
72     nv21.cb = data8 + area;
73     nv21.cr = data8 + area + (area >> 2);
74     nv21.ystride = width;
75     nv21.cstride = width / 2;
76     nv21.chroma_step = 1;
77 
78     return nv21;
79 }
80 
toNV21Shallow(const size_t width,const size_t height,const android_ycbcr & ycbcr,std::vector<uint8_t> * data)81 android_ycbcr toNV21Shallow(const size_t width, const size_t height,
82                             const android_ycbcr& ycbcr,
83                             std::vector<uint8_t>* data) {
84     LOG_ALWAYS_FATAL_IF((width & 1) || (height & 1));
85     if (ycbcr.chroma_step == 1) {
86         return ycbcr;
87     }
88 
89     const size_t area = width * height;
90     data->resize(area / 2);  // only for CbCr
91 
92     android_ycbcr nv21;
93     nv21.y = ycbcr.y;  // don't copy Y
94     nv21.ystride = ycbcr.ystride;
95     nv21.cb = &data[0];
96     nv21.cr = &data[area / 4];
97     nv21.cstride = width / 2;
98     nv21.chroma_step = 1;
99 
100     copyCbCrPlane(&((*data)[0]), width / 2, height / 2,
101                   ycbcr.cb, ycbcr.cstride, ycbcr.chroma_step);
102     copyCbCrPlane(&((*data)[area / 4]), width / 2, height / 2,
103                   ycbcr.cr, ycbcr.cstride, ycbcr.chroma_step);
104 
105     return nv21;
106 }
107 
108 }  // namespace yuv
109 }  // namespace implementation
110 }  // namespace provider
111 }  // namespace camera
112 }  // namespace hardware
113 }  // namespace android
114