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 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 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 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 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 61 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 71 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 84 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 92 bool StreamFormat::operator!=(const StreamFormat& other) const { 93 return !(*this == other); 94 } 95 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 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. 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|. 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 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