• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "dcamera_stream.h"
17 
18 #include "constants.h"
19 #include "dcamera.h"
20 #include "distributed_hardware_log.h"
21 #include "securec.h"
22 
23 namespace OHOS {
24 namespace DistributedHardware {
InitDCameraStream(const StreamInfo & info)25 DCamRetCode DCameraStream::InitDCameraStream(const StreamInfo &info)
26 {
27     if ((info.streamId_ < 0) || (info.width_ < 0) || (info.height_ < 0) ||
28         (info.format_ < 0) || (info.dataspace_ < 0)) {
29         DHLOGE("Stream info is invalid.");
30         return DCamRetCode::INVALID_ARGUMENT;
31     }
32     dcStreamId_ = info.streamId_;
33     dcStreamInfo_ = std::make_shared<StreamInfo>();
34     dcStreamInfo_->streamId_ = info.streamId_;
35     dcStreamInfo_->width_ = info.width_;
36     dcStreamInfo_->height_ = info.height_;
37     dcStreamInfo_->format_ = info.format_;
38     dcStreamInfo_->dataspace_ = info.dataspace_;
39     dcStreamInfo_->intent_ = info.intent_;
40     dcStreamInfo_->tunneledMode_ = info.tunneledMode_;
41     dcStreamInfo_->bufferQueue_ = info.bufferQueue_;
42     dcStreamInfo_->minFrameDuration_ = info.minFrameDuration_;
43 
44     dcStreamAttribute_.streamId_ = dcStreamInfo_->streamId_;
45     dcStreamAttribute_.width_ = dcStreamInfo_->width_;
46     dcStreamAttribute_.height_ = dcStreamInfo_->height_;
47     dcStreamAttribute_.overrideFormat_ = dcStreamInfo_->format_;
48     dcStreamAttribute_.overrideDataspace_ = dcStreamInfo_->dataspace_;
49     dcStreamAttribute_.producerUsage_ = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
50 
51     dcStreamAttribute_.producerBufferCount_ = BUFFER_QUEUE_SIZE;
52     dcStreamAttribute_.maxBatchCaptureCount_ = BUFFER_QUEUE_SIZE;
53     dcStreamAttribute_.maxCaptureCount_ = 1;
54 
55     DCamRetCode ret = DCamRetCode::SUCCESS;
56     if (dcStreamInfo_->bufferQueue_ != nullptr) {
57         ret = InitDCameraBufferManager();
58         if (ret != DCamRetCode::SUCCESS) {
59             DHLOGE("Cannot init buffer manager.");
60         }
61     }
62     isCancelBuffer_ = false;
63     isCancelCapture_ = false;
64     return ret;
65 }
66 
InitDCameraBufferManager()67 DCamRetCode DCameraStream::InitDCameraBufferManager()
68 {
69     if (dcStreamInfo_ == nullptr) {
70         DHLOGE("Distributed camera stream info is invalid.");
71         return DCamRetCode::INVALID_ARGUMENT;
72     }
73 
74     if (dcStreamInfo_->bufferQueue_ != nullptr && dcStreamInfo_->bufferQueue_->producer_ != nullptr) {
75         dcStreamProducer_ = OHOS::Surface::CreateSurfaceAsProducer(dcStreamInfo_->bufferQueue_->producer_);
76     }
77     if (dcStreamProducer_ == nullptr) {
78         DHLOGE("Distributed camera stream producer is invalid.");
79         return DCamRetCode::INVALID_ARGUMENT;
80     }
81     dcStreamBufferMgr_ = std::make_shared<DBufferManager>();
82 
83     DCamRetCode ret = DCamRetCode::SUCCESS;
84     if (!isBufferMgrInited_) {
85         ret = FinishCommitStream();
86     }
87     return ret;
88 }
89 
GetDCameraStreamInfo(shared_ptr<StreamInfo> & info)90 DCamRetCode DCameraStream::GetDCameraStreamInfo(shared_ptr<StreamInfo> &info)
91 {
92     if (!dcStreamInfo_) {
93         DHLOGE("Distributed camera stream info is not init.");
94         return DCamRetCode::FAILED;
95     }
96     info = dcStreamInfo_;
97     return DCamRetCode::SUCCESS;
98 }
99 
SetDCameraBufferQueue(const OHOS::sptr<BufferProducerSequenceable> & producer)100 DCamRetCode DCameraStream::SetDCameraBufferQueue(const OHOS::sptr<BufferProducerSequenceable> &producer)
101 {
102     if (dcStreamInfo_->bufferQueue_) {
103         DHLOGE("Stream [%d] has already have bufferQueue.", dcStreamId_);
104         return DCamRetCode::SUCCESS;
105     }
106 
107     dcStreamInfo_->bufferQueue_ = producer;
108     DCamRetCode ret = InitDCameraBufferManager();
109     if (ret != DCamRetCode::SUCCESS) {
110         DHLOGE("Init distributed camera buffer manager failed.");
111     }
112     return ret;
113 }
114 
ReleaseDCameraBufferQueue()115 DCamRetCode DCameraStream::ReleaseDCameraBufferQueue()
116 {
117     DCamRetCode ret = CancelDCameraBuffer();
118     if (ret != DCamRetCode::SUCCESS) {
119         DHLOGE("Release distributed camera buffer queue failed.");
120         return ret;
121     }
122 
123     std::lock_guard<std::mutex> lockBuffer(bufferQueueMutex_);
124     if (dcStreamInfo_->bufferQueue_ != nullptr) {
125         dcStreamInfo_->bufferQueue_->producer_ = nullptr;
126     }
127     dcStreamInfo_->bufferQueue_ = nullptr;
128     if (dcStreamProducer_ != nullptr) {
129         dcStreamProducer_->CleanCache();
130         dcStreamProducer_ = nullptr;
131     }
132     dcStreamBufferMgr_ = nullptr;
133 
134     return DCamRetCode::SUCCESS;
135 }
136 
GetDCameraStreamAttribute(StreamAttribute & attribute)137 DCamRetCode DCameraStream::GetDCameraStreamAttribute(StreamAttribute &attribute)
138 {
139     attribute = dcStreamAttribute_;
140     return DCamRetCode::SUCCESS;
141 }
142 
FinishCommitStream()143 DCamRetCode DCameraStream::FinishCommitStream()
144 {
145     if (isBufferMgrInited_) {
146         DHLOGI("Stream already inited.");
147         return DCamRetCode::SUCCESS;
148     }
149     if (dcStreamProducer_ == nullptr) {
150         DHLOGI("No bufferQueue.");
151         return DCamRetCode::SUCCESS;
152     }
153     dcStreamProducer_->SetQueueSize(BUFFER_QUEUE_SIZE);
154     isBufferMgrInited_ = true;
155 
156     for (uint32_t i = 0; i < BUFFER_QUEUE_SIZE; i++) {
157         GetNextRequest();
158     }
159     return DCamRetCode::SUCCESS;
160 }
161 
CheckRequestParam()162 DCamRetCode DCameraStream::CheckRequestParam()
163 {
164     if (!isBufferMgrInited_) {
165         DHLOGE("BufferManager not be init.");
166         return DCamRetCode::INVALID_ARGUMENT;
167     }
168     if (dcStreamInfo_ == nullptr) {
169         DHLOGE("Cannot create buffer manager by invalid streaminfo.");
170         return DCamRetCode::INVALID_ARGUMENT;
171     }
172     if (dcStreamProducer_ == nullptr) {
173         DHLOGE("Cannot create a buffer manager by invalid bufferqueue.");
174         return DCamRetCode::INVALID_ARGUMENT;
175     }
176 
177     return DCamRetCode::SUCCESS;
178 }
179 
GetNextRequest()180 DCamRetCode DCameraStream::GetNextRequest()
181 {
182     if (CheckRequestParam() != DCamRetCode::SUCCESS) {
183         return DCamRetCode::INVALID_ARGUMENT;
184     }
185 
186     OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer = nullptr;
187     OHOS::sptr<OHOS::SyncFence> syncFence = nullptr;
188     int32_t usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
189     OHOS::BufferRequestConfig config = {
190         .width = dcStreamInfo_->width_,
191         .height = dcStreamInfo_->height_,
192         .strideAlignment = 8,
193         .format = dcStreamInfo_->format_,
194         .usage = usage,
195         .timeout = 0
196     };
197 
198     OHOS::SurfaceError surfaceError = dcStreamProducer_->RequestBuffer(surfaceBuffer, syncFence, config);
199     if (surfaceError == OHOS::SURFACE_ERROR_NO_BUFFER) {
200         DHLOGE("No available buffer to request in surface.");
201         return DCamRetCode::EXCEED_MAX_NUMBER;
202     }
203 
204     if (surfaceError != OHOS::SURFACE_ERROR_OK || surfaceBuffer == nullptr) {
205         DHLOGE("Get producer buffer failed. [streamId = %d] [sfError = %d]", dcStreamInfo_->streamId_, surfaceError);
206         return DCamRetCode::EXCEED_MAX_NUMBER;
207     }
208 
209     std::shared_ptr<DImageBuffer> imageBuffer = std::make_shared<DImageBuffer>();
210     RetCode ret = DBufferManager::SurfaceBufferToDImageBuffer(surfaceBuffer, imageBuffer);
211     if (ret != RC_OK) {
212         DHLOGE("Convert surface buffer to image buffer failed, streamId = %d.", dcStreamInfo_->streamId_);
213         dcStreamProducer_->CancelBuffer(surfaceBuffer);
214         return DCamRetCode::EXCEED_MAX_NUMBER;
215     }
216 
217     imageBuffer->SetIndex(++index_);
218     imageBuffer->SetSyncFence(syncFence);
219     ret = dcStreamBufferMgr_->AddBuffer(imageBuffer);
220     if (ret != RC_OK) {
221         DHLOGE("Add buffer to buffer manager failed. [streamId = %d]", dcStreamInfo_->streamId_);
222         dcStreamProducer_->CancelBuffer(surfaceBuffer);
223         return DCamRetCode::EXCEED_MAX_NUMBER;
224     }
225     DHLOGD("Add new image buffer success: index = %d, fenceFd = %d", imageBuffer->GetIndex(), syncFence->Get());
226 
227     auto itr = bufferConfigMap_.find(imageBuffer);
228     if (itr == bufferConfigMap_.end()) {
229         auto bufferCfg = std::make_tuple(surfaceBuffer, usage);
230         bufferConfigMap_.insert(std::make_pair(imageBuffer, bufferCfg));
231     }
232 
233     return DCamRetCode::SUCCESS;
234 }
235 
GetDCameraBuffer(DCameraBuffer & buffer)236 DCamRetCode DCameraStream::GetDCameraBuffer(DCameraBuffer &buffer)
237 {
238     std::lock_guard<std::mutex> lockRequest(requestMutex_);
239     if (isCancelBuffer_ || isCancelCapture_) {
240         DHLOGE("Buffer has already canceled.");
241         return DCamRetCode::FAILED;
242     }
243     {
244         std::lock_guard<std::mutex> lockBuffer(bufferQueueMutex_);
245         DCamRetCode retCode = GetNextRequest();
246         if (retCode != DCamRetCode::SUCCESS && retCode != DCamRetCode::EXCEED_MAX_NUMBER) {
247             DHLOGE("Get next request failed.");
248             return retCode;
249         }
250 
251         if (dcStreamBufferMgr_ == nullptr) {
252             DHLOGE("dcStreamBufferMgr_ is nullptr");
253             return DCamRetCode::FAILED;
254         }
255         std::shared_ptr<DImageBuffer> imageBuffer = dcStreamBufferMgr_->AcquireBuffer();
256         if (imageBuffer == nullptr) {
257             DHLOGE("Cannot get idle buffer.");
258             return DCamRetCode::EXCEED_MAX_NUMBER;
259         }
260         auto syncFence = imageBuffer->GetSyncFence();
261         if (syncFence != nullptr) {
262             syncFence->Wait(BUFFER_SYNC_FENCE_TIMEOUT);
263         }
264         RetCode ret = DBufferManager::DImageBufferToDCameraBuffer(imageBuffer, buffer);
265         if (ret != RC_OK) {
266             DHLOGE("Convert image buffer to distributed camera buffer failed.");
267             return DCamRetCode::FAILED;
268         }
269     }
270 
271     {
272         std::lock_guard<std::mutex> lockSync(lockSync_);
273         captureBufferCount_++;
274     }
275     DHLOGD("Get buffer success. index = %d, size = %d", buffer.index_, buffer.size_);
276     return DCamRetCode::SUCCESS;
277 }
278 
FlushDCameraBuffer(const DCameraBuffer & buffer)279 DCamRetCode DCameraStream::FlushDCameraBuffer(const DCameraBuffer &buffer)
280 {
281     std::lock_guard<std::mutex> lockBuffer(bufferQueueMutex_);
282     shared_ptr<DImageBuffer> imageBuffer = nullptr;
283     for (auto iter = bufferConfigMap_.begin(); iter != bufferConfigMap_.end(); ++iter) {
284         if (buffer.index_ == iter->first->GetIndex()) {
285             imageBuffer = iter->first;
286             break;
287         }
288     }
289     if (imageBuffer == nullptr) {
290         DHLOGE("Cannot found image buffer, buffer index = %d.", buffer.index_);
291         return DCamRetCode::INVALID_ARGUMENT;
292     }
293 
294     if (dcStreamBufferMgr_ != nullptr) {
295         RetCode ret = dcStreamBufferMgr_->RemoveBuffer(imageBuffer);
296         if (ret != RC_OK) {
297             DHLOGE("Buffer manager remove buffer failed: %d", ret);
298         }
299     }
300 
301     auto bufCfg = bufferConfigMap_.find(imageBuffer);
302     if (bufCfg == bufferConfigMap_.end()) {
303         DHLOGE("Cannot get bufferConfig.");
304         return DCamRetCode::INVALID_ARGUMENT;
305     }
306     auto surfaceBuffer = std::get<0>(bufCfg->second);
307     OHOS::BufferFlushConfig flushConf = {
308         .damage = { .x = 0, .y = 0, .w = dcStreamInfo_->width_, .h = dcStreamInfo_->height_ },
309         .timestamp = 0
310     };
311     if (dcStreamProducer_ != nullptr) {
312         SetSurfaceBuffer(surfaceBuffer, buffer);
313         OHOS::sptr<OHOS::SyncFence> autoFence(new(std::nothrow) OHOS::SyncFence(-1));
314         int ret = dcStreamProducer_->FlushBuffer(surfaceBuffer, autoFence, flushConf);
315         if (ret != 0) {
316             DHLOGI("FlushBuffer error: %d", ret);
317         }
318     }
319     bufferConfigMap_.erase(bufCfg);
320     return DCamRetCode::SUCCESS;
321 }
322 
ReturnDCameraBuffer(const DCameraBuffer & buffer)323 DCamRetCode DCameraStream::ReturnDCameraBuffer(const DCameraBuffer &buffer)
324 {
325     DCamRetCode ret = FlushDCameraBuffer(buffer);
326     if (ret != DCamRetCode::SUCCESS) {
327         DHLOGE("Flush Buffer failed, ret: %d", ret);
328         return ret;
329     }
330 
331     {
332         std::lock_guard<std::mutex> lockSync(lockSync_);
333         captureBufferCount_--;
334     }
335     cv_.notify_one();
336     return DCamRetCode::SUCCESS;
337 }
338 
SetSurfaceBuffer(OHOS::sptr<OHOS::SurfaceBuffer> & surfaceBuffer,const DCameraBuffer & buffer)339 void DCameraStream::SetSurfaceBuffer(OHOS::sptr<OHOS::SurfaceBuffer>& surfaceBuffer, const DCameraBuffer &buffer)
340 {
341     if (dcStreamInfo_->intent_ == StreamIntent::VIDEO) {
342         int32_t size = (dcStreamInfo_->width_) * (dcStreamInfo_->height_) * YUV_WIDTH_RATIO / YUV_HEIGHT_RATIO;
343         int64_t timeStamp = static_cast<int64_t>(GetVideoTimeStamp());
344         surfaceBuffer->GetExtraData()->ExtraSet("dataSize", size);
345         surfaceBuffer->GetExtraData()->ExtraSet("isKeyFrame", (int32_t)0);
346         surfaceBuffer->GetExtraData()->ExtraSet("timeStamp", timeStamp);
347     } else if (dcStreamInfo_->intent_ == StreamIntent::STILL_CAPTURE) {
348         int32_t size = buffer.size_;
349         int64_t timeStamp = static_cast<int64_t>(GetCurrentLocalTimeStamp());
350         surfaceBuffer->GetExtraData()->ExtraSet("dataSize", size);
351         surfaceBuffer->GetExtraData()->ExtraSet("isKeyFrame", (int32_t)0);
352         surfaceBuffer->GetExtraData()->ExtraSet("timeStamp", timeStamp);
353     }
354 }
355 
GetVideoTimeStamp()356 uint64_t DCameraStream::GetVideoTimeStamp()
357 {
358     struct timespec tp;
359     clock_gettime(CLOCK_MONOTONIC, &tp);
360     return tp.tv_sec * SEC_TO_NSEC_TIMES + tp.tv_nsec;
361 }
362 
DoCapture()363 void DCameraStream::DoCapture()
364 {
365     DHLOGI("Do capture, streamId %d", dcStreamInfo_->streamId_);
366     std::lock_guard<std::mutex> lockRequest(requestMutex_);
367     isCancelCapture_ = false;
368 }
369 
CancelCaptureWait()370 void DCameraStream::CancelCaptureWait()
371 {
372     DHLOGI("Cancel capture wait for, streamId %d", dcStreamInfo_->streamId_);
373     std::lock_guard<std::mutex> lockRequest(requestMutex_);
374     if (isCancelCapture_) {
375         DHLOGI("CacelCapture has already execute");
376         return;
377     }
378     if (captureBufferCount_ != 0) {
379         DHLOGI("StreamId:%d has request that not return and wait, captureBufferCount=%d",
380             dcStreamInfo_->streamId_, captureBufferCount_);
381     }
382     {
383         std::unique_lock<std::mutex> lockSync(lockSync_);
384         cv_.wait(lockSync, [this] { return !captureBufferCount_; });
385     }
386     isCancelCapture_ = true;
387     DHLOGI("Cancel capture wait for success, streamId %d", dcStreamInfo_->streamId_);
388     return;
389 }
390 
CancelDCameraBuffer()391 DCamRetCode DCameraStream::CancelDCameraBuffer()
392 {
393     DHLOGI("Cancel dcamera buffer wait for, streamId %d", dcStreamInfo_->streamId_);
394     std::lock_guard<std::mutex> lockRequest(requestMutex_);
395     if (dcStreamBufferMgr_ == nullptr || dcStreamProducer_ == nullptr || isCancelBuffer_) {
396         DHLOGE("BufferManager or Producer is null or isCanceled is true.");
397         return DCamRetCode::SUCCESS;
398     }
399 
400     if (captureBufferCount_ != 0) {
401         DHLOGI("StreamId:%d has request that not return, captureBufferCount=%d",
402             dcStreamInfo_->streamId_, captureBufferCount_);
403     }
404     {
405         std::unique_lock<std::mutex> lockSync(lockSync_);
406         cv_.wait(lockSync, [this] { return !captureBufferCount_; });
407     }
408 
409     {
410         std::lock_guard<std::mutex> lockBuffer(bufferQueueMutex_);
411         while (true) {
412             std::shared_ptr<DImageBuffer> imageBuffer = dcStreamBufferMgr_->AcquireBuffer();
413             if (imageBuffer != nullptr) {
414                 auto bufCfg = bufferConfigMap_.find(imageBuffer);
415                 if (bufCfg == bufferConfigMap_.end()) {
416                     DHLOGE("Buffer not in map.");
417                     return DCamRetCode::INVALID_ARGUMENT;
418                 }
419                 auto surfaceBuffer = std::get<0>(bufCfg->second);
420                 if (dcStreamProducer_ != nullptr) {
421                     dcStreamProducer_->CancelBuffer(surfaceBuffer);
422                 }
423                 bufferConfigMap_.erase(bufCfg);
424             } else {
425                 break;
426             }
427         }
428         index_ = -1;
429     }
430     captureBufferCount_ = 0;
431     isCancelBuffer_ = true;
432     DHLOGI("Cancel dcamera buffer wait for success, streamId %d", dcStreamInfo_->streamId_);
433     return DCamRetCode::SUCCESS;
434 }
435 
HasBufferQueue()436 bool DCameraStream::HasBufferQueue()
437 {
438     if (dcStreamProducer_ == nullptr || !isBufferMgrInited_) {
439         return false;
440     }
441     return true;
442 }
443 } // namespace DistributedHardware
444 } // namespace OHOS
445