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