Home | History | Annotate | Download | only in 3_4
      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