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 26namespace v4l2_camera_hal { 27 28using arc::SupportedFormat; 29using arc::SupportedFormats; 30 31static 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 38StreamFormat::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 47StreamFormat::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 56StreamFormat::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 64void 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 74FormatCategory 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 87bool 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 95bool StreamFormat::operator!=(const StreamFormat& other) const { 96 return !(*this == other); 97} 98 99int 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 122uint32_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. 150bool 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|. 187bool 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 201SupportedFormats 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