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