blob: 2fcef355fe816a0b069fd7e30718c42ec7be9668 [file] [log] [blame]
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -07001/*
2 * Copyright (C) 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
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -070017#include "v4l2_gralloc.h"
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070018
19#include <linux/videodev2.h>
20
21#include <cstdlib>
22
23#include <hardware/camera3.h>
24#include <hardware/gralloc.h>
25#include <system/graphics.h>
26
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -070027#include "common.h"
Ari Hausman-Cohen04570102016-09-02 15:50:21 -070028#include "stream_format.h"
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070029
30namespace v4l2_camera_hal {
31
32// Copy |height| lines from |src| to |dest|,
33// where |src| and |dest| may have different line lengths.
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -070034void copyWithPadding(uint8_t* dest,
35 const uint8_t* src,
36 size_t dest_stride,
37 size_t src_stride,
38 size_t height) {
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070039 size_t copy_stride = dest_stride;
40 if (copy_stride > src_stride) {
41 // Adding padding, not reducing. 0 out the extra memory.
42 memset(dest, 0, src_stride * height);
43 copy_stride = src_stride;
44 }
45 uint8_t* dest_line_start = dest;
46 const uint8_t* src_line_start = src;
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -070047 for (size_t row = 0; row < height;
48 ++row, dest_line_start += dest_stride, src_line_start += src_stride) {
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070049 memcpy(dest_line_start, src_line_start, copy_stride);
50 }
51}
52
Ari Hausman-Cohen681eaa22016-07-21 16:28:17 -070053V4L2Gralloc* V4L2Gralloc::NewV4L2Gralloc() {
Ari Hausman-Cohen681eaa22016-07-21 16:28:17 -070054 // Initialize and check the gralloc module.
55 const hw_module_t* module = nullptr;
56 int res = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
57 if (res || !module) {
58 HAL_LOGE("Couldn't get gralloc module.");
59 return nullptr;
60 }
61 const gralloc_module_t* gralloc =
62 reinterpret_cast<const gralloc_module_t*>(module);
63
64 // This class only supports Gralloc v0, not Gralloc V1.
65 if (gralloc->common.module_api_version > GRALLOC_MODULE_API_VERSION_0_3) {
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -070066 HAL_LOGE(
67 "Invalid gralloc version %x. Only 0.3 (%x) "
68 "and below are supported by this HAL.",
69 gralloc->common.module_api_version,
70 GRALLOC_MODULE_API_VERSION_0_3);
Ari Hausman-Cohen681eaa22016-07-21 16:28:17 -070071 return nullptr;
72 }
73
74 return new V4L2Gralloc(gralloc);
75}
76
77// Private. As checked by above factory, module will be non-null
78// and a supported version.
Ari Hausman-Cohenad6fe2b2016-11-16 10:48:07 -080079V4L2Gralloc::V4L2Gralloc(const gralloc_module_t* module) : mModule(module) {}
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070080
81V4L2Gralloc::~V4L2Gralloc() {
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070082 // Unlock buffers that are still locked.
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -070083 unlockAllBuffers();
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070084}
85
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070086int V4L2Gralloc::lock(const camera3_stream_buffer_t* camera_buffer,
87 uint32_t bytes_per_line,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070088 v4l2_buffer* device_buffer) {
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070089 // Lock the camera buffer (varies depending on if the buffer is YUV or not).
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -070090 std::unique_ptr<BufferData> buffer_data(
91 new BufferData{camera_buffer, nullptr, bytes_per_line});
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070092 buffer_handle_t buffer = *camera_buffer->buffer;
93 void* data;
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070094 camera3_stream_t* stream = camera_buffer->stream;
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -070095 int ret = 0;
96 switch (StreamFormat::HalToV4L2PixelFormat(stream->format)) {
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070097 // TODO(b/30119452): support more YCbCr formats.
Ari Hausman-Cohen04570102016-09-02 15:50:21 -070098 case V4L2_PIX_FMT_YUV420:
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070099 android_ycbcr yuv_data;
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700100 ret = mModule->lock_ycbcr(mModule,
101 buffer,
102 stream->usage,
103 0,
104 0,
105 stream->width,
106 stream->height,
107 &yuv_data);
108 if (ret) {
109 HAL_LOGE("Failed to lock ycbcr buffer: %d", ret);
110 return ret;
111 }
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700112
113 // Check if gralloc format matches v4l2 format
114 // (same padding, not interleaved, contiguous).
115 if (yuv_data.ystride == bytes_per_line &&
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700116 yuv_data.cstride == bytes_per_line / 2 && yuv_data.chroma_step == 1 &&
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700117 (reinterpret_cast<uint8_t*>(yuv_data.cb) ==
118 reinterpret_cast<uint8_t*>(yuv_data.y) +
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700119 (stream->height * yuv_data.ystride)) &&
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700120 (reinterpret_cast<uint8_t*>(yuv_data.cr) ==
121 reinterpret_cast<uint8_t*>(yuv_data.cb) +
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700122 (stream->height / 2 * yuv_data.cstride))) {
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700123 // If so, great, point to the beginning.
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700124 data = yuv_data.y;
125 } else {
126 // If not, allocate a contiguous buffer of appropriate size
127 // (to be transformed back upon unlock).
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700128 data = new uint8_t[device_buffer->length];
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700129 // Make a dynamically-allocated copy of yuv_data,
130 // since it will be needed at transform time.
131 buffer_data->transform_dest.reset(new android_ycbcr(yuv_data));
132 }
133 break;
Ari Hausman-Cohen04570102016-09-02 15:50:21 -0700134 case V4L2_PIX_FMT_JPEG:
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700135 // Jpeg buffers are just contiguous blobs; lock length * 1.
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700136 ret = mModule->lock(mModule,
137 buffer,
138 stream->usage,
139 0,
140 0,
141 device_buffer->length,
142 1,
143 &data);
144 if (ret) {
145 HAL_LOGE("Failed to lock jpeg buffer: %d", ret);
146 return ret;
147 }
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700148 break;
Jaesung Chung424744c2017-11-09 12:51:32 +0900149 case V4L2_PIX_FMT_RGB24: // Fall-through.
Ari Hausman-Cohen04570102016-09-02 15:50:21 -0700150 case V4L2_PIX_FMT_BGR32: // Fall-through.
151 case V4L2_PIX_FMT_RGB32:
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700152 // RGB formats have nice agreed upon representation. Unless using android
153 // flex formats.
154 ret = mModule->lock(mModule,
155 buffer,
156 stream->usage,
157 0,
158 0,
159 stream->width,
160 stream->height,
161 &data);
162 if (ret) {
163 HAL_LOGE("Failed to lock RGB buffer: %d", ret);
164 return ret;
165 }
Ari Hausman-Cohen04570102016-09-02 15:50:21 -0700166 break;
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700167 default:
168 return -EINVAL;
169 }
170
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700171 if (!data) {
172 ALOGE("Gralloc lock returned null ptr");
173 return -ENODEV;
174 }
175
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700176 // Set up the device buffer.
177 static_assert(sizeof(unsigned long) >= sizeof(void*),
178 "void* must be able to fit in the v4l2_buffer m.userptr "
179 "field (unsigned long) for this code to work");
180 device_buffer->m.userptr = reinterpret_cast<unsigned long>(data);
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700181
182 // Note the mapping of data:buffer info for when unlock is called.
183 mBufferMap.emplace(data, buffer_data.release());
184
185 return 0;
186}
187
188int V4L2Gralloc::unlock(const v4l2_buffer* device_buffer) {
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700189 // TODO(b/30000211): support multi-planar data (video_capture_mplane).
190 if (device_buffer->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
191 return -EINVAL;
192 }
193
194 void* data = reinterpret_cast<void*>(device_buffer->m.userptr);
195
196 // Find and pop the matching entry in the map.
197 auto map_entry = mBufferMap.find(data);
198 if (map_entry == mBufferMap.end()) {
199 HAL_LOGE("No matching buffer for data at %p", data);
200 return -EINVAL;
201 }
202 std::unique_ptr<const BufferData> buffer_data(map_entry->second);
203 mBufferMap.erase(map_entry);
204
205 const camera3_stream_buffer_t* camera_buffer = buffer_data->camera_buffer;
206 const buffer_handle_t buffer = *camera_buffer->buffer;
207
Jaesung Chung424744c2017-11-09 12:51:32 +0900208 if (StreamFormat::HalToV4L2PixelFormat(camera_buffer->stream->format) == V4L2_PIX_FMT_RGB24) {
209 // Convert RGB24 to RGB32.
210 size_t rgb_size = camera_buffer->stream->width * camera_buffer->stream->height;
211 uint8_t* tail_rgb24 = (uint8_t*)data + 3 * rgb_size - 1;
212 uint8_t* tail_rgb32 = (uint8_t*)data + 4 * rgb_size - 1;
213 for (int i = 0; i < rgb_size; i++) {
214 *(tail_rgb32--) = 0xff;
215 *(tail_rgb32--) = *(tail_rgb24--);
216 *(tail_rgb32--) = *(tail_rgb24--);
217 *(tail_rgb32--) = *(tail_rgb24--);
218 }
219 }
220
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700221 // Check for transform.
222 if (buffer_data->transform_dest) {
223 HAL_LOGV("Transforming V4L2 YUV to gralloc YUV.");
224 // In this case data was allocated by this class, put it in a unique_ptr
225 // to ensure it gets cleaned up no matter which way this function exits.
226 std::unique_ptr<uint8_t[]> data_cleanup(reinterpret_cast<uint8_t*>(data));
227
228 uint32_t bytes_per_line = buffer_data->v4l2_bytes_per_line;
229 android_ycbcr* yuv_data = buffer_data->transform_dest.get();
230
231 // Should only occur in error situations.
232 if (device_buffer->bytesused == 0) {
233 return -EINVAL;
234 }
235
236 // Transform V4L2 to Gralloc, copying each plane to the correct place,
237 // adjusting padding, and interleaving if necessary.
238 uint32_t height = camera_buffer->stream->height;
239 // Y data first.
240 size_t y_len = bytes_per_line * height;
241 if (yuv_data->ystride == bytes_per_line) {
242 // Data should match exactly.
243 memcpy(yuv_data->y, data, y_len);
244 } else {
245 HAL_LOGV("Changing padding on Y plane from %u to %u.",
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700246 bytes_per_line,
247 yuv_data->ystride);
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700248 // Wrong padding from V4L2.
249 copyWithPadding(reinterpret_cast<uint8_t*>(yuv_data->y),
250 reinterpret_cast<uint8_t*>(data),
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700251 yuv_data->ystride,
252 bytes_per_line,
253 height);
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700254 }
255 // C data.
256 // TODO(b/30119452): These calculations assume YCbCr_420_888.
257 size_t c_len = y_len / 4;
258 uint32_t c_bytes_per_line = bytes_per_line / 2;
259 // V4L2 is packed, meaning the data is stored as contiguous {y, cb, cr}.
260 uint8_t* cb_device = reinterpret_cast<uint8_t*>(data) + y_len;
261 uint8_t* cr_device = cb_device + c_len;
262 size_t step = yuv_data->chroma_step;
263 if (step == 1) {
264 // Still planar.
265 if (yuv_data->cstride == c_bytes_per_line) {
266 // Data should match exactly.
267 memcpy(yuv_data->cb, cb_device, c_len);
268 memcpy(yuv_data->cr, cr_device, c_len);
269 } else {
270 HAL_LOGV("Changing padding on C plane from %u to %u.",
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700271 c_bytes_per_line,
272 yuv_data->cstride);
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700273 // Wrong padding from V4L2.
274 copyWithPadding(reinterpret_cast<uint8_t*>(yuv_data->cb),
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700275 cb_device,
276 yuv_data->cstride,
277 c_bytes_per_line,
278 height / 2);
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700279 copyWithPadding(reinterpret_cast<uint8_t*>(yuv_data->cr),
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700280 cr_device,
281 yuv_data->cstride,
282 c_bytes_per_line,
283 height / 2);
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700284 }
285 } else {
286 // Desire semiplanar (cb and cr interleaved).
287 HAL_LOGV("Interleaving cb and cr. Padding going from %u to %u.",
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700288 c_bytes_per_line,
289 yuv_data->cstride);
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700290 uint32_t c_height = height / 2;
291 uint32_t c_width = camera_buffer->stream->width / 2;
292 // Zero out destination
293 uint8_t* cb_gralloc = reinterpret_cast<uint8_t*>(yuv_data->cb);
294 uint8_t* cr_gralloc = reinterpret_cast<uint8_t*>(yuv_data->cr);
295 memset(cb_gralloc, 0, c_width * c_height * step);
296
297 // Interleaving means we need to copy the cb and cr bytes one by one.
298 for (size_t line = 0; line < c_height; ++line,
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700299 cb_gralloc += yuv_data->cstride,
300 cr_gralloc += yuv_data->cstride,
301 cb_device += c_bytes_per_line,
302 cr_device += c_bytes_per_line) {
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700303 for (size_t i = 0; i < c_width; ++i) {
304 *(cb_gralloc + (i * step)) = *(cb_device + i);
305 *(cr_gralloc + (i * step)) = *(cr_device + i);
306 }
307 }
308 }
309 }
310
311 // Unlock.
312 int res = mModule->unlock(mModule, buffer);
313 if (res) {
314 HAL_LOGE("Failed to unlock buffer at %p", buffer);
315 return -ENODEV;
316 }
317
318 return 0;
319}
320
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700321int V4L2Gralloc::unlockAllBuffers() {
322 HAL_LOG_ENTER();
323
324 bool failed = false;
325 for (auto const& entry : mBufferMap) {
326 int res = mModule->unlock(mModule, *entry.second->camera_buffer->buffer);
327 if (res) {
328 failed = true;
329 }
330 // When there is a transform to be made, the buffer returned by lock()
331 // is dynamically allocated (to hold the pre-transform data).
332 if (entry.second->transform_dest) {
Ari Hausman-Cohenfbac1742016-09-19 14:03:13 -0700333 delete[] reinterpret_cast<uint8_t*>(entry.first);
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700334 }
335 // The BufferData entry is always dynamically allocated in lock().
336 delete entry.second;
337 }
Ari Hausman-Cohenc5a48522016-11-16 10:53:52 -0800338 mBufferMap.clear();
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700339
340 // If any unlock failed, return error.
341 if (failed) {
342 return -ENODEV;
343 }
344
345 return 0;
346}
347
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -0700348} // namespace default_camera_hal