blob: 64fa306044211e4dcd3bf06a9005ccafa6aa1edd [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.
34void copyWithPadding(uint8_t* dest, const uint8_t* src, size_t dest_stride,
35 size_t src_stride, size_t height) {
36 size_t copy_stride = dest_stride;
37 if (copy_stride > src_stride) {
38 // Adding padding, not reducing. 0 out the extra memory.
39 memset(dest, 0, src_stride * height);
40 copy_stride = src_stride;
41 }
42 uint8_t* dest_line_start = dest;
43 const uint8_t* src_line_start = src;
44 for (size_t row = 0; row < height; ++row,
45 dest_line_start += dest_stride, src_line_start += src_stride) {
46 memcpy(dest_line_start, src_line_start, copy_stride);
47 }
48}
49
Ari Hausman-Cohen681eaa22016-07-21 16:28:17 -070050V4L2Gralloc* V4L2Gralloc::NewV4L2Gralloc() {
51 HAL_LOG_ENTER();
52
53 // Initialize and check the gralloc module.
54 const hw_module_t* module = nullptr;
55 int res = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
56 if (res || !module) {
57 HAL_LOGE("Couldn't get gralloc module.");
58 return nullptr;
59 }
60 const gralloc_module_t* gralloc =
61 reinterpret_cast<const gralloc_module_t*>(module);
62
63 // This class only supports Gralloc v0, not Gralloc V1.
64 if (gralloc->common.module_api_version > GRALLOC_MODULE_API_VERSION_0_3) {
65 HAL_LOGE("Invalid gralloc version %x. Only 0.3 (%x) "
66 "and below are supported by this HAL.",
67 gralloc->common.module_api_version,
68 GRALLOC_MODULE_API_VERSION_0_3);
69 return nullptr;
70 }
71
72 return new V4L2Gralloc(gralloc);
73}
74
75// Private. As checked by above factory, module will be non-null
76// and a supported version.
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070077V4L2Gralloc::V4L2Gralloc(const gralloc_module_t* module)
78 : mModule(module) {
79 HAL_LOG_ENTER();
80}
81
82V4L2Gralloc::~V4L2Gralloc() {
83 HAL_LOG_ENTER();
84
85 // Unlock buffers that are still locked.
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -070086 unlockAllBuffers();
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070087}
88
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070089int V4L2Gralloc::lock(const camera3_stream_buffer_t* camera_buffer,
90 uint32_t bytes_per_line,
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -070091 v4l2_buffer* device_buffer) {
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070092 HAL_LOG_ENTER();
93
94 // Lock the camera buffer (varies depending on if the buffer is YUV or not).
95 std::unique_ptr<BufferData> buffer_data(new BufferData {
96 camera_buffer, nullptr, bytes_per_line});
97 buffer_handle_t buffer = *camera_buffer->buffer;
98 void* data;
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -070099 camera3_stream_t* stream = camera_buffer->stream;
Ari Hausman-Cohen04570102016-09-02 15:50:21 -0700100 switch(StreamFormat::HalToV4L2PixelFormat(stream->format)) {
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700101 // TODO(b/30119452): support more YCbCr formats.
Ari Hausman-Cohen04570102016-09-02 15:50:21 -0700102 case V4L2_PIX_FMT_YUV420:
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700103 android_ycbcr yuv_data;
104 mModule->lock_ycbcr(mModule, buffer, stream->usage, 0, 0,
105 stream->width, stream->height, &yuv_data);
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700106
107 // Check if gralloc format matches v4l2 format
108 // (same padding, not interleaved, contiguous).
109 if (yuv_data.ystride == bytes_per_line &&
110 yuv_data.cstride == bytes_per_line / 2 &&
111 yuv_data.chroma_step == 1 &&
112 (reinterpret_cast<uint8_t*>(yuv_data.cb) ==
113 reinterpret_cast<uint8_t*>(yuv_data.y) +
114 (stream->height * yuv_data.ystride)) &&
115 (reinterpret_cast<uint8_t*>(yuv_data.cr) ==
116 reinterpret_cast<uint8_t*>(yuv_data.cb) +
117 (stream->height / 2 * yuv_data.cstride))) {
118 // If so, great, point to the beginning.
119 HAL_LOGV("V4L2 YUV matches gralloc YUV.");
120 data = yuv_data.y;
121 } else {
122 // If not, allocate a contiguous buffer of appropriate size
123 // (to be transformed back upon unlock).
124 HAL_LOGV("Need to transform V4L2 YUV to gralloc YUV.");
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700125 data = new uint8_t[device_buffer->length];
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700126 // Make a dynamically-allocated copy of yuv_data,
127 // since it will be needed at transform time.
128 buffer_data->transform_dest.reset(new android_ycbcr(yuv_data));
129 }
130 break;
Ari Hausman-Cohen04570102016-09-02 15:50:21 -0700131 case V4L2_PIX_FMT_JPEG:
Ari Hausman-Cohen9e6fd982016-08-02 16:29:53 -0700132 // Jpeg buffers are just contiguous blobs; lock length * 1.
133 mModule->lock(mModule, buffer, stream->usage, 0, 0, device_buffer->length, 1, &data);
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700134 break;
Ari Hausman-Cohen04570102016-09-02 15:50:21 -0700135 case V4L2_PIX_FMT_BGR32: // Fall-through.
136 case V4L2_PIX_FMT_RGB32:
137 // RGB formats have nice agreed upon representation. Unless using android flex formats.
138 mModule->lock(mModule, buffer, stream->usage, 0, 0, stream->width, stream->height, &data);
139 break;
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700140 default:
141 return -EINVAL;
142 }
143
144 // Set up the device buffer.
145 static_assert(sizeof(unsigned long) >= sizeof(void*),
146 "void* must be able to fit in the v4l2_buffer m.userptr "
147 "field (unsigned long) for this code to work");
148 device_buffer->m.userptr = reinterpret_cast<unsigned long>(data);
Ari Hausman-Cohen3eece6f2016-07-21 11:08:24 -0700149
150 // Note the mapping of data:buffer info for when unlock is called.
151 mBufferMap.emplace(data, buffer_data.release());
152
153 return 0;
154}
155
156int V4L2Gralloc::unlock(const v4l2_buffer* device_buffer) {
157 HAL_LOG_ENTER();
158
159 // TODO(b/30000211): support multi-planar data (video_capture_mplane).
160 if (device_buffer->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
161 return -EINVAL;
162 }
163
164 void* data = reinterpret_cast<void*>(device_buffer->m.userptr);
165
166 // Find and pop the matching entry in the map.
167 auto map_entry = mBufferMap.find(data);
168 if (map_entry == mBufferMap.end()) {
169 HAL_LOGE("No matching buffer for data at %p", data);
170 return -EINVAL;
171 }
172 std::unique_ptr<const BufferData> buffer_data(map_entry->second);
173 mBufferMap.erase(map_entry);
174
175 const camera3_stream_buffer_t* camera_buffer = buffer_data->camera_buffer;
176 const buffer_handle_t buffer = *camera_buffer->buffer;
177
178 // Check for transform.
179 if (buffer_data->transform_dest) {
180 HAL_LOGV("Transforming V4L2 YUV to gralloc YUV.");
181 // In this case data was allocated by this class, put it in a unique_ptr
182 // to ensure it gets cleaned up no matter which way this function exits.
183 std::unique_ptr<uint8_t[]> data_cleanup(reinterpret_cast<uint8_t*>(data));
184
185 uint32_t bytes_per_line = buffer_data->v4l2_bytes_per_line;
186 android_ycbcr* yuv_data = buffer_data->transform_dest.get();
187
188 // Should only occur in error situations.
189 if (device_buffer->bytesused == 0) {
190 return -EINVAL;
191 }
192
193 // Transform V4L2 to Gralloc, copying each plane to the correct place,
194 // adjusting padding, and interleaving if necessary.
195 uint32_t height = camera_buffer->stream->height;
196 // Y data first.
197 size_t y_len = bytes_per_line * height;
198 if (yuv_data->ystride == bytes_per_line) {
199 // Data should match exactly.
200 memcpy(yuv_data->y, data, y_len);
201 } else {
202 HAL_LOGV("Changing padding on Y plane from %u to %u.",
203 bytes_per_line, yuv_data->ystride);
204 // Wrong padding from V4L2.
205 copyWithPadding(reinterpret_cast<uint8_t*>(yuv_data->y),
206 reinterpret_cast<uint8_t*>(data),
207 yuv_data->ystride, bytes_per_line, height);
208 }
209 // C data.
210 // TODO(b/30119452): These calculations assume YCbCr_420_888.
211 size_t c_len = y_len / 4;
212 uint32_t c_bytes_per_line = bytes_per_line / 2;
213 // V4L2 is packed, meaning the data is stored as contiguous {y, cb, cr}.
214 uint8_t* cb_device = reinterpret_cast<uint8_t*>(data) + y_len;
215 uint8_t* cr_device = cb_device + c_len;
216 size_t step = yuv_data->chroma_step;
217 if (step == 1) {
218 // Still planar.
219 if (yuv_data->cstride == c_bytes_per_line) {
220 // Data should match exactly.
221 memcpy(yuv_data->cb, cb_device, c_len);
222 memcpy(yuv_data->cr, cr_device, c_len);
223 } else {
224 HAL_LOGV("Changing padding on C plane from %u to %u.",
225 c_bytes_per_line, yuv_data->cstride);
226 // Wrong padding from V4L2.
227 copyWithPadding(reinterpret_cast<uint8_t*>(yuv_data->cb),
228 cb_device, yuv_data->cstride,
229 c_bytes_per_line, height / 2);
230 copyWithPadding(reinterpret_cast<uint8_t*>(yuv_data->cr),
231 cr_device, yuv_data->cstride,
232 c_bytes_per_line, height / 2);
233 }
234 } else {
235 // Desire semiplanar (cb and cr interleaved).
236 HAL_LOGV("Interleaving cb and cr. Padding going from %u to %u.",
237 c_bytes_per_line, yuv_data->cstride);
238 uint32_t c_height = height / 2;
239 uint32_t c_width = camera_buffer->stream->width / 2;
240 // Zero out destination
241 uint8_t* cb_gralloc = reinterpret_cast<uint8_t*>(yuv_data->cb);
242 uint8_t* cr_gralloc = reinterpret_cast<uint8_t*>(yuv_data->cr);
243 memset(cb_gralloc, 0, c_width * c_height * step);
244
245 // Interleaving means we need to copy the cb and cr bytes one by one.
246 for (size_t line = 0; line < c_height; ++line,
247 cb_gralloc += yuv_data->cstride, cr_gralloc += yuv_data->cstride,
248 cb_device += c_bytes_per_line, cr_device += c_bytes_per_line) {
249 for (size_t i = 0; i < c_width; ++i) {
250 *(cb_gralloc + (i * step)) = *(cb_device + i);
251 *(cr_gralloc + (i * step)) = *(cr_device + i);
252 }
253 }
254 }
255 }
256
257 // Unlock.
258 int res = mModule->unlock(mModule, buffer);
259 if (res) {
260 HAL_LOGE("Failed to unlock buffer at %p", buffer);
261 return -ENODEV;
262 }
263
264 return 0;
265}
266
Ari Hausman-Cohen4ab49622016-07-21 14:33:54 -0700267int V4L2Gralloc::unlockAllBuffers() {
268 HAL_LOG_ENTER();
269
270 bool failed = false;
271 for (auto const& entry : mBufferMap) {
272 int res = mModule->unlock(mModule, *entry.second->camera_buffer->buffer);
273 if (res) {
274 failed = true;
275 }
276 // When there is a transform to be made, the buffer returned by lock()
277 // is dynamically allocated (to hold the pre-transform data).
278 if (entry.second->transform_dest) {
279 delete [] reinterpret_cast<uint8_t*>(entry.first);
280 }
281 // The BufferData entry is always dynamically allocated in lock().
282 delete entry.second;
283 }
284
285 // If any unlock failed, return error.
286 if (failed) {
287 return -ENODEV;
288 }
289
290 return 0;
291}
292
Ari Hausman-Cohen3841a7f2016-07-19 17:27:52 -0700293} // namespace default_camera_hal