• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021–2022 Beijing OSWare Technology Co., Ltd
3  * This file contains confidential and proprietary information of
4  * OSWare Technology Co., Ltd
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <cerrno>
20 #include <cstdio>
21 #include <string>
22 #include "v4l2_buffer.h"
23 namespace OHOS::Camera {
HosV4L2Buffers(enum v4l2_memory memType,enum v4l2_buf_type bufferType)24 HosV4L2Buffers::HosV4L2Buffers(enum v4l2_memory memType, enum v4l2_buf_type bufferType)
25     : memoryType_(memType), bufferType_(bufferType)
26 {
27     additional_info_ = Imx8mmImageAdditionalInfo::GetInstance();
28 }
29 
~HosV4L2Buffers()30 HosV4L2Buffers::~HosV4L2Buffers()
31 {
32     delete(additional_info_);
33 }
34 
V4L2ReqBuffers(int fd,int unsigned buffCont)35 RetCode HosV4L2Buffers::V4L2ReqBuffers(int fd, int unsigned buffCont)
36 {
37     struct v4l2_requestbuffers req = {};
38 
39     CAMERA_LOGD("V4L2ReqBuffers buffCont %d\n", buffCont);
40 
41     req.count = buffCont;
42     req.type = bufferType_;
43     req.memory = memoryType_;
44     adapterBufferList = (struct AdapterBuffer*)calloc(req.count, sizeof(struct AdapterBuffer));
45 
46     if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
47         CAMERA_LOGE("does not support memory mapping %s\n", strerror(errno));
48         return RC_ERROR;
49     }
50 
51     if (req.count != buffCont) {
52         CAMERA_LOGE("error Insufficient buffer memory on \n");
53 
54         req.count = 0;
55         req.type = bufferType_;
56         req.memory = memoryType_;
57         if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
58             CAMERA_LOGE("V4L2ReqBuffers does not release buffer	%s\n", strerror(errno));
59             return RC_ERROR;
60         }
61 
62         return RC_ERROR;
63     }
64 
65     return RC_OK;
66 }
67 
V4L2QueueBuffer(int fd,const std::shared_ptr<FrameSpec> & frameSpec)68 RetCode HosV4L2Buffers::V4L2QueueBuffer(int fd, const std::shared_ptr<FrameSpec>& frameSpec)
69 {
70     struct v4l2_buffer buf = {};
71     struct v4l2_plane planes[1] = {};
72 
73     if (frameSpec == nullptr) {
74         CAMERA_LOGE("V4L2QueueBuffer: frameSpec is NULL\n");
75         return RC_ERROR;
76     }
77 
78     uint32_t index = (uint32_t)frameSpec->buffer_->GetIndex();
79     adapterBufferList[index].userBufPtr = frameSpec->buffer_->GetVirAddress();
80     adapterBufferList[index].length = additional_info_->GetLength();
81 
82     buf.index = (uint32_t)frameSpec->buffer_->GetIndex();
83     buf.type = bufferType_;
84     buf.memory = memoryType_;
85 
86     if (bufferType_ == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
87         buf.m.planes = planes;
88         buf.m.planes[0].length = frameSpec->buffer_->GetSize();
89         buf.m.planes[0].m.userptr = (unsigned long)frameSpec->buffer_->GetVirAddress();
90         buf.length = 1;
91 
92         CAMERA_LOGD("++++++++++++ V4L2QueueBuffer buf.index = %{public}d, buf.length = \
93             %{public}d, buf.m.userptr = %{public}p\n", \
94             buf.index, buf.m.planes[0].length, (void*)buf.m.planes[0].m.userptr);
95     } else if (bufferType_ == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
96         switch (memoryType_) {
97             case V4L2_MEMORY_MMAP:
98                 {
99                     adapterBufferList[index].start = mmap(NULL, additional_info_->GetLength(),
100                         PROT_READ | PROT_WRITE, MAP_SHARED, fd, additional_info_->GetOffset());
101                     if (MAP_FAILED == adapterBufferList[index].start) {
102                         CAMERA_LOGE("v4l2 mmap failed\n");
103                         return RC_ERROR;
104                     }
105                     CAMERA_LOGD("++++++++++++ V4L2QueueBuffer buf.index = %{public}d, buf.length = \
106                         %{public}d, adapterBufferList[%{public}d].start = %{public}p\n", \
107                         buf.index, buf.length, index, (void*)adapterBufferList[index].start);
108 
109                     break;
110                 }
111             case V4L2_MEMORY_USERPTR:
112                 {
113                     buf.length = frameSpec->buffer_->GetSize();
114                     buf.m.userptr = (unsigned long)frameSpec->buffer_->GetVirAddress();
115 
116                     CAMERA_LOGD("++++++++++++ V4L2QueueBuffer buf.index = %{public}d, buf.length = \
117                         %{public}d, buf.m.userptr = %{public}p\n", \
118                         buf.index, buf.length, (void*)buf.m.userptr);
119                     break;
120                 }
121             default:
122                 CAMERA_LOGE("It can not be happening - incorrect memory type\n");
123                 return RC_ERROR;
124         }
125     }
126 
127     std::lock_guard<std::mutex> l(bufferLock_);
128     int rc = ioctl(fd, VIDIOC_QBUF, &buf);
129     if (rc < 0) {
130         CAMERA_LOGE("ioctl VIDIOC_QBUF failed: %s\n", strerror(errno));
131         return RC_ERROR;
132     }
133 
134     auto itr = queueBuffers_.find(fd);
135     if (itr != queueBuffers_.end()) {
136         itr->second[buf.index] = frameSpec;
137         CAMERA_LOGD("insert frameMap fd = %{public}d buf.index = %{public}d\n", fd, buf.index);
138     } else {
139         FrameMap frameMap;
140         frameMap.insert(std::make_pair(buf.index, frameSpec));
141         queueBuffers_.insert(std::make_pair(fd, frameMap));
142         CAMERA_LOGD("insert fd = %{public}d buf.index = %{public}d\n", fd, buf.index);
143     }
144 
145     return RC_OK;
146 }
147 
V4L2DequeueBuffer(int fd)148 RetCode HosV4L2Buffers::V4L2DequeueBuffer(int fd)
149 {
150     struct v4l2_buffer buf = {};
151     struct v4l2_plane planes[1] = {};
152 
153     buf.type = bufferType_;
154     buf.memory = memoryType_;
155 
156     if (bufferType_ == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
157         buf.m.planes = planes;
158         buf.length = 1;
159     }
160     int rc = ioctl(fd, VIDIOC_DQBUF, &buf);
161     if (rc < 0) {
162         CAMERA_LOGE("ioctl VIDIOC_DQBUF failed: %s\n", strerror(errno));
163         return RC_ERROR;
164     }
165 
166     if (bufferType_ == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
167         CAMERA_LOGD("---------------- V4L2DequeueBuffer index = %{public}d buf.m.ptr = %{public}p len = %{public}d\n",
168             buf.index, (void*)buf.m.planes[0].m.userptr, buf.m.planes[0].length);
169     } else if (bufferType_ == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
170         CAMERA_LOGD("---------------- V4L2DequeueBuffer index = %{public}d buf.m.ptr = %{public}p len = %{public}d\n",
171             buf.index, (void*)buf.m.userptr, buf.length);
172     }
173 
174     if (memoryType_ == V4L2_MEMORY_MMAP) {
175         memcpy(adapterBufferList[buf.index].userBufPtr,
176             adapterBufferList[buf.index].start, adapterBufferList[buf.index].length);
177 
178         if (munmap(adapterBufferList[buf.index].start, adapterBufferList[buf.index].length) < 0) {
179             CAMERA_LOGE("munmap is fail\n");
180             return RC_ERROR;
181         }
182     }
183 
184     auto IterMap = queueBuffers_.find(fd);
185     if (IterMap == queueBuffers_.end()) {
186         CAMERA_LOGE("std::map queueBuffers_ no fd\n");
187         return RC_ERROR;
188     }
189     auto& bufferMap = IterMap->second;
190 
191     auto Iter = bufferMap.find(buf.index);
192     if (Iter == bufferMap.end()) {
193         CAMERA_LOGE("V4L2DequeueBuffer buf.index == %{public}d is not find in FrameMap\n", buf.index);
194         return RC_ERROR;
195     }
196 
197     if (dequeueBuffer_ == nullptr) {
198         CAMERA_LOGE("V4L2DequeueBuffer buf.index == %{public}d no callback\n", buf.index);
199         std::lock_guard<std::mutex> l(bufferLock_);
200         bufferMap.erase(Iter);
201         return RC_ERROR;
202     }
203 
204     // callback to up
205     dequeueBuffer_(Iter->second);
206     std::lock_guard<std::mutex> l(bufferLock_);
207     bufferMap.erase(Iter);
208 
209     return RC_OK;
210 }
211 
V4L2AllocBuffer(int fd,const std::shared_ptr<FrameSpec> & frameSpec)212 RetCode HosV4L2Buffers::V4L2AllocBuffer(int fd, const std::shared_ptr<FrameSpec>& frameSpec)
213 {
214     struct v4l2_buffer buf = {};
215     struct v4l2_plane planes[1] = {};
216     CAMERA_LOGD("V4L2AllocBuffer\n");
217 
218     if (frameSpec == nullptr) {
219         CAMERA_LOGE("V4L2AllocBuffer frameSpec is NULL\n");
220         return RC_ERROR;
221     }
222 
223     switch (memoryType_) {
224         case V4L2_MEMORY_MMAP:
225         case V4L2_MEMORY_USERPTR:
226             buf.type = bufferType_;
227             buf.memory = memoryType_;
228             buf.index = (uint32_t)frameSpec->buffer_->GetIndex();
229 
230             if (bufferType_ == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
231                 buf.m.planes = planes;
232                 buf.length = 1;
233             }
234             CAMERA_LOGD("V4L2_MEMORY_USERPTR Print the cnt: %{public}d\n", buf.index);
235 
236             if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) {
237                 CAMERA_LOGE("error: ioctl VIDIOC_QUERYBUF failed: %{public}s\n", strerror(errno));
238                 return RC_ERROR;
239             }
240 
241             CAMERA_LOGD("buf.length = %{public}d frameSpec->buffer_->GetSize() = %{public}d\n", buf.length,
242                         frameSpec->buffer_->GetSize());
243 
244             if (buf.length > frameSpec->buffer_->GetSize()) {
245                 CAMERA_LOGE("ERROR:user buff < V4L2 buf.length\n");
246                 return RC_ERROR;
247             }
248             additional_info_->SetLength(buf.length);
249             additional_info_->SetOffset(buf.m.offset);
250 
251             break;
252         case V4L2_MEMORY_OVERLAY:
253             // to do something
254             break;
255 
256         case V4L2_MEMORY_DMABUF:
257             // to do something
258             break;
259 
260         default:
261             CAMERA_LOGE("It can not be happening - incorrect memory type\n");
262             return RC_ERROR;
263     }
264 
265     return RC_OK;
266 }
267 
V4L2ReleaseBuffers(int fd)268 RetCode HosV4L2Buffers::V4L2ReleaseBuffers(int fd)
269 {
270     CAMERA_LOGE("HosV4L2Buffers::V4L2ReleaseBuffers\n");
271 
272     std::lock_guard<std::mutex> l(bufferLock_);
273     queueBuffers_.erase(fd);
274 
275     return V4L2ReqBuffers(fd, 0);
276 }
277 
SetCallback(BufCallback cb)278 void HosV4L2Buffers::SetCallback(BufCallback cb)
279 {
280     CAMERA_LOGD("HosV4L2Buffers::SetCallback OK.");
281     dequeueBuffer_ = cb;
282 }
Flush(int fd)283 RetCode HosV4L2Buffers::Flush(int fd)
284 {
285     CAMERA_LOGE("HosV4L2Buffers::Flush\n");
286     return RC_OK;
287 }
288 } // namespace OHOS::Camera
289