liyujie
2025-08-28 d9927380ed7c8366f762049be9f3fee225860833
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 * Copyright (c) 2021 by Allwinnertech Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
#include "stream_format.h"
 
#include <linux/videodev2.h>
#include <system/graphics.h>
 
#include "v4l2_log.h"
 
namespace v4l2_camera_hal {
 
StreamFormat::StreamFormat(int format, uint32_t width, uint32_t height)
    // TODO(b/30000211): multiplanar support.
    : type_(V4L2_CAPTURE_TYPE),
      memory_(V4L2_MEMORY_MMAP),
      v4l2_pixel_format_(StreamFormat::HalToV4L2PixelFormat(format)),
      width_(width),
      height_(height),
      // Be compatibility with GPU, DE, VE, CSI, ISP.
      // Now we set the bytes_per_line_ as width
      // because the drivers return this one.
      bytes_per_line_(width) {}
 
StreamFormat::StreamFormat(const v4l2_format& format, bool mergeStreamFlag)
    // be compatibility with multiplanar and single planar.
    : type_(format.type),
      memory_(V4L2_MEMORY_MMAP),
      nplanes_(format.fmt.pix_mp.num_planes),
      // TODO(b/30000211): multiplanar support.
      v4l2_pixel_format_(format.fmt.pix_mp.pixelformat),
      width_(format.fmt.pix_mp.width),
      height_(format.fmt.pix_mp.height),
      bytes_per_line_(format.fmt.pix_mp.width),
      merge_stream_flag_(mergeStreamFlag){}
 
void StreamFormat::FillFormatRequest(v4l2_format* format) const {
  memset(format, 0, sizeof(*format));
  format->type = type_;
  format->fmt.pix_mp.pixelformat = v4l2_pixel_format_;
  format->fmt.pix_mp.width = width_;
  format->fmt.pix_mp.height = height_;
  // Bytes per line and min buffer size are outputs set by the driver,
  // not part of the request.
}
 
FormatCategory StreamFormat::Category() const {
  switch (v4l2_pixel_format_) {
    case V4L2_PIX_FMT_JPEG:
      return kFormatCategoryStalling;
    case V4L2_PIX_FMT_YUV420:  // Fall through.
    case V4L2_PIX_FMT_BGR32:
      return kFormatCategoryNonStalling;
    default:
      // Note: currently no supported RAW formats.
      return kFormatCategoryUnknown;
  }
}
 
bool StreamFormat::operator==(const StreamFormat& other) const {
  // Used to check that a requested format was actually set, so
  // don't compare bytes per line or min buffer size.
  return (type_ == other.type_ &&
      v4l2_pixel_format_ == other.v4l2_pixel_format_ &&
      width_ == other.width_ && height_ == other.height_);
}
 
bool StreamFormat::operator!=(const StreamFormat& other) const {
  return !(*this == other);
}
 
int StreamFormat::V4L2ToHalPixelFormat(uint32_t v4l2_pixel_format) {
  HAL_LOGD("Get v4l2_pixel_format %s",
      getV4l2PixelFormatString(v4l2_pixel_format).c_str());
  // Translate V4L2 format to HAL format.
  int hal_pixel_format = -1;
  switch (v4l2_pixel_format) {
    case V4L2_PIX_FMT_JPEG:
      hal_pixel_format = HAL_PIXEL_FORMAT_BLOB;
      break;
    case V4L2_PIX_FMT_NV21:
      hal_pixel_format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
      HAL_LOGD("Set format as %s for GPU",
          getHalPixelFormatString(hal_pixel_format).c_str());
      break;
    case V4L2_PIX_FMT_NV12:
      hal_pixel_format = HAL_PIXEL_FORMAT_YCbCr_420_888;
      HAL_LOGD("Set format as %s",
          getHalPixelFormatString(hal_pixel_format).c_str());
      break;
    case V4L2_PIX_FMT_YUV420:
      hal_pixel_format = HAL_PIXEL_FORMAT_YCbCr_420_888;
      HAL_LOGD("Set format as %s",
          getHalPixelFormatString(hal_pixel_format).c_str());
      break;
    case V4L2_PIX_FMT_BGR32:
      hal_pixel_format = HAL_PIXEL_FORMAT_RGBA_8888;
      HAL_LOGD("Set format as %s",
          getHalPixelFormatString(hal_pixel_format).c_str());
      break;
    default:
      // Unrecognized format.
      if (getV4l2PixelFormatString(v4l2_pixel_format) != "") {
        HAL_LOGV("Unrecognized v4l2 pixel format %s",
            getV4l2PixelFormatString(v4l2_pixel_format).c_str());
      } else {
        HAL_LOGV("Unrecognized v4l2 pixel format %u", v4l2_pixel_format);
      }
      break;
  }
  return hal_pixel_format;
}
 
uint32_t StreamFormat::HalToV4L2PixelFormat(int hal_pixel_format) {
  // Translate HAL format to V4L2 format.
  uint32_t v4l2_pixel_format = 0;
  switch (hal_pixel_format) {
    case HAL_PIXEL_FORMAT_RGBA_8888:
      // Should be RGB32, but RPi doesn't support that.
      // For now we accept that the colors will be off.
      v4l2_pixel_format = V4L2_PIX_FMT_BGR32;
      break;
      // Set the default format between CSI and GPU-gralloc
      // with HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED.
      // In CSI we see the HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
      // as V4L2_PIX_FMT_NV21.
      // In GPU they see the HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
      // as HAL_PIXEL_FORMAT_YCrCb_420_SP.
      // PS: In CSI V4L2_PIX_FMT_YVU420 equals YV12.
      //    In CSI V4L2_PIX_FMT_YUV420 equals YV21.
      // keep the HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED for MPLANE.
    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:  // fall-through.
      v4l2_pixel_format = V4L2_PIX_FMT_NV21;
      break;
    case HAL_PIXEL_FORMAT_YCrCb_420_SP:
      v4l2_pixel_format = V4L2_PIX_FMT_NV21;
      break;
    case HAL_PIXEL_FORMAT_YCbCr_420_888:
      v4l2_pixel_format = V4L2_PIX_FMT_NV21;
      break;
    case HAL_PIXEL_FORMAT_BLOB:
      v4l2_pixel_format = V4L2_PIX_FMT_JPEG;
      break;
    default:
      // Unrecognized format.
      HAL_LOGV("Unrecognized HAL pixel format %d", hal_pixel_format);
      break;
  }
  HAL_LOGD("HAL pixel format is %s. set v4l2_pixel_format to %s",
      getHalPixelFormatString(hal_pixel_format).c_str(),
      getV4l2PixelFormatString(v4l2_pixel_format).c_str());
  return v4l2_pixel_format;
}
 
bool StreamFormat::GetMergeStreamFlag() {
  return merge_stream_flag_;
}
 
}  // namespace v4l2_camera_hal