1 /*
2 * Copyright 2016 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 "stream_format.h"
18
19 #include <linux/videodev2.h>
20
21 #include <system/graphics.h>
22
23 #include "arc/image_processor.h"
24 #include "common.h"
25
26 namespace v4l2_camera_hal {
27
28 using arc::SupportedFormat;
29 using arc::SupportedFormats;
30
GetSupportedFourCCs()31 static const std::vector<uint32_t> GetSupportedFourCCs() {
32 // The preference of supported fourccs in the list is from high to low.
33 static const std::vector<uint32_t> kSupportedFourCCs = {V4L2_PIX_FMT_YUYV,
34 V4L2_PIX_FMT_MJPEG};
35 return kSupportedFourCCs;
36 }
37
StreamFormat(int format,uint32_t width,uint32_t height)38 StreamFormat::StreamFormat(int format, uint32_t width, uint32_t height)
39 // TODO(b/30000211): multiplanar support.
40 : type_(V4L2_BUF_TYPE_VIDEO_CAPTURE),
41 v4l2_pixel_format_(StreamFormat::HalToV4L2PixelFormat(format)),
42 width_(width),
43 height_(height),
44 bytes_per_line_(0),
45 min_buffer_size_(0) {}
46
StreamFormat(const v4l2_format & format)47 StreamFormat::StreamFormat(const v4l2_format& format)
48 : type_(format.type),
49 // TODO(b/30000211): multiplanar support.
50 v4l2_pixel_format_(format.fmt.pix.pixelformat),
51 width_(format.fmt.pix.width),
52 height_(format.fmt.pix.height),
53 bytes_per_line_(format.fmt.pix.bytesperline),
54 min_buffer_size_(format.fmt.pix.sizeimage) {}
55
StreamFormat(const arc::SupportedFormat & format)56 StreamFormat::StreamFormat(const arc::SupportedFormat& format)
57 : type_(V4L2_BUF_TYPE_VIDEO_CAPTURE),
58 v4l2_pixel_format_(format.fourcc),
59 width_(format.width),
60 height_(format.height),
61 bytes_per_line_(0),
62 min_buffer_size_(0) {}
63
FillFormatRequest(v4l2_format * format) const64 void StreamFormat::FillFormatRequest(v4l2_format* format) const {
65 memset(format, 0, sizeof(*format));
66 format->type = type_;
67 format->fmt.pix.pixelformat = v4l2_pixel_format_;
68 format->fmt.pix.width = width_;
69 format->fmt.pix.height = height_;
70 // Bytes per line and min buffer size are outputs set by the driver,
71 // not part of the request.
72 }
73
Category() const74 FormatCategory StreamFormat::Category() const {
75 switch (v4l2_pixel_format_) {
76 case V4L2_PIX_FMT_JPEG:
77 return kFormatCategoryStalling;
78 case V4L2_PIX_FMT_YUV420: // Fall through.
79 case V4L2_PIX_FMT_BGR32:
80 return kFormatCategoryNonStalling;
81 default:
82 // Note: currently no supported RAW formats.
83 return kFormatCategoryUnknown;
84 }
85 }
86
operator ==(const StreamFormat & other) const87 bool StreamFormat::operator==(const StreamFormat& other) const {
88 // Used to check that a requested format was actually set, so
89 // don't compare bytes per line or min buffer size.
90 return (type_ == other.type_ &&
91 v4l2_pixel_format_ == other.v4l2_pixel_format_ &&
92 width_ == other.width_ && height_ == other.height_);
93 }
94
operator !=(const StreamFormat & other) const95 bool StreamFormat::operator!=(const StreamFormat& other) const {
96 return !(*this == other);
97 }
98
V4L2ToHalPixelFormat(uint32_t v4l2_pixel_format)99 int StreamFormat::V4L2ToHalPixelFormat(uint32_t v4l2_pixel_format) {
100 // Translate V4L2 format to HAL format.
101 switch (v4l2_pixel_format) {
102 case V4L2_PIX_FMT_BGR32:
103 return HAL_PIXEL_FORMAT_RGBA_8888;
104 case V4L2_PIX_FMT_JPEG:
105 return HAL_PIXEL_FORMAT_BLOB;
106 case V4L2_PIX_FMT_NV21:
107 return HAL_PIXEL_FORMAT_YCrCb_420_SP;
108 case V4L2_PIX_FMT_YUV420:
109 return HAL_PIXEL_FORMAT_YCbCr_420_888;
110 case V4L2_PIX_FMT_YUYV:
111 return HAL_PIXEL_FORMAT_YCbCr_422_I;
112 case V4L2_PIX_FMT_YVU420:
113 return HAL_PIXEL_FORMAT_YV12;
114 default:
115 // Unrecognized format.
116 HAL_LOGV("Unrecognized v4l2 pixel format %u", v4l2_pixel_format);
117 break;
118 }
119 return -1;
120 }
121
HalToV4L2PixelFormat(int hal_pixel_format)122 uint32_t StreamFormat::HalToV4L2PixelFormat(int hal_pixel_format) {
123 switch (hal_pixel_format) {
124 case HAL_PIXEL_FORMAT_BLOB:
125 return V4L2_PIX_FMT_JPEG;
126 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: // Fall-through
127 case HAL_PIXEL_FORMAT_RGBA_8888:
128 return V4L2_PIX_FMT_BGR32;
129 case HAL_PIXEL_FORMAT_YCbCr_420_888:
130 // This is a flexible YUV format that depends on platform. Different
131 // platform may have different format. It can be YVU420 or NV12. Now we
132 // return YVU420 first.
133 // TODO(): call drm_drv.get_fourcc() to get correct format.
134 return V4L2_PIX_FMT_YUV420;
135 case HAL_PIXEL_FORMAT_YCbCr_422_I:
136 return V4L2_PIX_FMT_YUYV;
137 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
138 return V4L2_PIX_FMT_NV21;
139 case HAL_PIXEL_FORMAT_YV12:
140 return V4L2_PIX_FMT_YVU420;
141 default:
142 HAL_LOGV("Pixel format 0x%x is unsupported.", hal_pixel_format);
143 break;
144 }
145 return -1;
146 }
147
148 // Copy the qualified format into out_format and return true if there is a
149 // proper and fitting format in the given format lists.
FindBestFitFormat(const SupportedFormats & supported_formats,const SupportedFormats & qualified_formats,uint32_t fourcc,uint32_t width,uint32_t height,SupportedFormat * out_format)150 bool StreamFormat::FindBestFitFormat(const SupportedFormats& supported_formats,
151 const SupportedFormats& qualified_formats,
152 uint32_t fourcc, uint32_t width,
153 uint32_t height,
154 SupportedFormat* out_format) {
155 // Match exact format and resolution if possible.
156 for (const auto& format : supported_formats) {
157 if (format.fourcc == fourcc && format.width == width &&
158 format.height == height) {
159 if (out_format != NULL) {
160 *out_format = format;
161 }
162 return true;
163 }
164 }
165 // All conversions will be done through CachedFrame for now, which will
166 // immediately convert the qualified format into YU12 (YUV420). We check
167 // here that the conversion between YU12 and |fourcc| is supported.
168 if (!arc::ImageProcessor::SupportsConversion(V4L2_PIX_FMT_YUV420, fourcc)) {
169 HAL_LOGE("Conversion between YU12 and 0x%x not supported.", fourcc);
170 return false;
171 }
172
173 // Choose the qualified format with a matching resolution.
174 for (const auto& format : qualified_formats) {
175 if (format.width == width && format.height == height) {
176 if (out_format != NULL) {
177 *out_format = format;
178 }
179 return true;
180 }
181 }
182 return false;
183 }
184
185 // Copy corresponding format into out_format and return true by matching
186 // resolution |width|x|height| in |formats|.
FindFormatByResolution(const SupportedFormats & formats,uint32_t width,uint32_t height,SupportedFormat * out_format)187 bool StreamFormat::FindFormatByResolution(const SupportedFormats& formats,
188 uint32_t width, uint32_t height,
189 SupportedFormat* out_format) {
190 for (const auto& format : formats) {
191 if (format.width == width && format.height == height) {
192 if (out_format != NULL) {
193 *out_format = format;
194 }
195 return true;
196 }
197 }
198 return false;
199 }
200
GetQualifiedFormats(const SupportedFormats & supported_formats)201 SupportedFormats StreamFormat::GetQualifiedFormats(
202 const SupportedFormats& supported_formats) {
203 // The preference of supported fourccs in the list is from high to low.
204 const std::vector<uint32_t> supported_fourccs = GetSupportedFourCCs();
205 SupportedFormats qualified_formats;
206 for (const auto& supported_fourcc : supported_fourccs) {
207 for (const auto& supported_format : supported_formats) {
208 if (supported_format.fourcc != supported_fourcc) {
209 continue;
210 }
211
212 // Skip if |qualified_formats| already has the same resolution with a more
213 // preferred fourcc.
214 if (FindFormatByResolution(qualified_formats, supported_format.width,
215 supported_format.height, NULL)) {
216 continue;
217 }
218 qualified_formats.push_back(supported_format);
219 }
220 }
221 return qualified_formats;
222 }
223
224 } // namespace v4l2_camera_hal
225