1 /*
2  * Copyright (c) 2021-2024 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     CHECK_AND_RETURN_RET_LOG(dcStreamInfo_ == nullptr, DCamRetCode::FAILED, "dcStreamInfo_ is nullptr");
103     if (dcStreamInfo_->bufferQueue_) {
104         DHLOGE("Stream [%{public}d] has already have bufferQueue.", dcStreamId_);
105         return DCamRetCode::SUCCESS;
106     }
107 
108     dcStreamInfo_->bufferQueue_ = producer;
109     DCamRetCode ret = InitDCameraBufferManager();
110     if (ret != DCamRetCode::SUCCESS) {
111         DHLOGE("Init distributed camera buffer manager failed.");
112     }
113     return ret;
114 }
115 
ReleaseDCameraBufferQueue()116 DCamRetCode DCameraStream::ReleaseDCameraBufferQueue()
117 {
118     DCamRetCode ret = CancelDCameraBuffer();
119     if (ret != DCamRetCode::SUCCESS) {
120         DHLOGE("Release distributed camera buffer queue failed.");
121         return ret;
122     }
123 
124     std::lock_guard<std::mutex> lockBuffer(bufferQueueMutex_);
125     if (dcStreamInfo_ != nullptr && dcStreamInfo_->bufferQueue_ != nullptr) {
126         dcStreamInfo_->bufferQueue_->producer_ = nullptr;
127         dcStreamInfo_->bufferQueue_ = nullptr;
128     }
129     if (dcStreamProducer_ != nullptr) {
130         dcStreamProducer_->CleanCache();
131         dcStreamProducer_ = nullptr;
132     }
133     dcStreamBufferMgr_ = nullptr;
134 
135     return DCamRetCode::SUCCESS;
136 }
137 
GetDCameraStreamAttribute(StreamAttribute & attribute)138 DCamRetCode DCameraStream::GetDCameraStreamAttribute(StreamAttribute &attribute)
139 {
140     attribute = dcStreamAttribute_;
141     return DCamRetCode::SUCCESS;
142 }
143 
FinishCommitStream()144 DCamRetCode DCameraStream::FinishCommitStream()
145 {
146     if (isBufferMgrInited_) {
147         DHLOGI("Stream already inited.");
148         return DCamRetCode::SUCCESS;
149     }
150     if (dcStreamProducer_ == nullptr) {
151         DHLOGI("No bufferQueue.");
152         return DCamRetCode::SUCCESS;
153     }
154     dcStreamProducer_->SetQueueSize(BUFFER_QUEUE_SIZE);
155     isBufferMgrInited_ = true;
156 
157     for (uint32_t i = 0; i < BUFFER_QUEUE_SIZE; i++) {
158         GetNextRequest();
159     }
160     return DCamRetCode::SUCCESS;
161 }
162 
CheckRequestParam()163 DCamRetCode DCameraStream::CheckRequestParam()
164 {
165     if (!isBufferMgrInited_) {
166         DHLOGE("BufferManager not be init.");
167         return DCamRetCode::INVALID_ARGUMENT;
168     }
169     if (dcStreamInfo_ == nullptr) {
170         DHLOGE("Cannot create buffer manager by invalid streaminfo.");
171         return DCamRetCode::INVALID_ARGUMENT;
172     }
173     if (dcStreamProducer_ == nullptr) {
174         DHLOGE("Cannot create a buffer manager by invalid bufferqueue.");
175         return DCamRetCode::INVALID_ARGUMENT;
176     }
177 
178     return DCamRetCode::SUCCESS;
179 }
180 
GetNextRequest()181 DCamRetCode DCameraStream::GetNextRequest()
182 {
183     if (CheckRequestParam() != DCamRetCode::SUCCESS) {
184         return DCamRetCode::INVALID_ARGUMENT;
185     }
186 
187     OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer = nullptr;
188     OHOS::sptr<OHOS::SyncFence> syncFence = nullptr;
189     int32_t usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
190     CHECK_AND_RETURN_RET_LOG(dcStreamInfo_ == nullptr, DCamRetCode::INVALID_ARGUMENT, "dcStreamInfo_ is nullptr");
191     OHOS::BufferRequestConfig config = {
192         .width = dcStreamInfo_->width_,
193         .height = dcStreamInfo_->height_,
194         .strideAlignment = 8,
195         .format = dcStreamInfo_->format_,
196         .usage = usage,
197         .timeout = 0
198     };
199 
200     if (dcStreamInfo_->intent_ == StreamIntent::STILL_CAPTURE) {
201         DHLOGI("Photographing stream.");
202         config.width = JPEG_MAX_SIZE;
203         config.height = 1;
204         config.format = GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BLOB;
205     }
206     CHECK_AND_RETURN_RET_LOG(
207         dcStreamProducer_ == nullptr, DCamRetCode::INVALID_ARGUMENT, "dcStreamProducer_ is nullptr");
208     OHOS::SurfaceError surfaceError = dcStreamProducer_->RequestBuffer(surfaceBuffer, syncFence, config);
209     if (surfaceError == OHOS::SURFACE_ERROR_NO_BUFFER) {
210         DHLOGE("No available buffer to request in surface.");
211         return DCamRetCode::EXCEED_MAX_NUMBER;
212     }
213 
214     if (surfaceError != OHOS::SURFACE_ERROR_OK || surfaceBuffer == nullptr) {
215         DHLOGE("Get producer buffer failed. [streamId = %{public}d] [sfError = %{public}d]",
216             dcStreamInfo_->streamId_, surfaceError);
217         return DCamRetCode::EXCEED_MAX_NUMBER;
218     }
219     return SurfaceBufferToDImageBuffer(surfaceBuffer, syncFence);
220 }
221 
SurfaceBufferToDImageBuffer(OHOS::sptr<OHOS::SurfaceBuffer> & surfaceBuffer,OHOS::sptr<OHOS::SyncFence> & syncFence)222 DCamRetCode DCameraStream::SurfaceBufferToDImageBuffer(OHOS::sptr<OHOS::SurfaceBuffer> &surfaceBuffer,
223     OHOS::sptr<OHOS::SyncFence> &syncFence)
224 {
225     std::shared_ptr<DImageBuffer> imageBuffer = std::make_shared<DImageBuffer>();
226     RetCode ret = DBufferManager::SurfaceBufferToDImageBuffer(surfaceBuffer, imageBuffer);
227     if (ret != RC_OK) {
228         DHLOGE("Convert surfacebuffer to image buffer failed, streamId = %{public}d.", dcStreamInfo_->streamId_);
229         dcStreamProducer_->CancelBuffer(surfaceBuffer);
230         return DCamRetCode::EXCEED_MAX_NUMBER;
231     }
232 
233     imageBuffer->SetIndex(++index_);
234     imageBuffer->SetSyncFence(syncFence);
235     CHECK_AND_RETURN_RET_LOG(
236         dcStreamBufferMgr_ == nullptr, DCamRetCode::INVALID_ARGUMENT, "dcStreamBufferMgr_ is nullptr");
237     ret = dcStreamBufferMgr_->AddBuffer(imageBuffer);
238     if (ret != RC_OK) {
239         DHLOGE("Add buffer to buffer manager failed. [streamId = %{public}d]", dcStreamInfo_->streamId_);
240         dcStreamProducer_->CancelBuffer(surfaceBuffer);
241         return DCamRetCode::EXCEED_MAX_NUMBER;
242     }
243     DHLOGD("Add new image buffer success: index = %{public}d, fenceFd = %{public}d", imageBuffer->GetIndex(),
244         syncFence->Get());
245     auto itr = bufferConfigMap_.find(imageBuffer);
246     if (itr == bufferConfigMap_.end()) {
247         int32_t usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
248         auto bufferCfg = std::make_tuple(surfaceBuffer, usage);
249         bufferConfigMap_.insert(std::make_pair(imageBuffer, bufferCfg));
250     }
251     return DCamRetCode::SUCCESS;
252 }
253 
GetDCameraBuffer(DCameraBuffer & buffer)254 DCamRetCode DCameraStream::GetDCameraBuffer(DCameraBuffer &buffer)
255 {
256     std::lock_guard<std::mutex> lockRequest(requestMutex_);
257     if (isCancelBuffer_ || isCancelCapture_) {
258         DHLOGE("Buffer has already canceled.");
259         return DCamRetCode::FAILED;
260     }
261     {
262         std::lock_guard<std::mutex> lockBuffer(bufferQueueMutex_);
263         DCamRetCode retCode = GetNextRequest();
264         if (retCode != DCamRetCode::SUCCESS && retCode != DCamRetCode::EXCEED_MAX_NUMBER) {
265             DHLOGE("Get next request failed.");
266             return retCode;
267         }
268 
269         if (dcStreamBufferMgr_ == nullptr) {
270             DHLOGE("dcStreamBufferMgr_ is nullptr");
271             return DCamRetCode::FAILED;
272         }
273         std::shared_ptr<DImageBuffer> imageBuffer = dcStreamBufferMgr_->AcquireBuffer();
274         if (imageBuffer == nullptr) {
275             DHLOGE("Cannot get idle buffer.");
276             return DCamRetCode::EXCEED_MAX_NUMBER;
277         }
278         auto syncFence = imageBuffer->GetSyncFence();
279         if (syncFence != nullptr) {
280             syncFence->Wait(BUFFER_SYNC_FENCE_TIMEOUT);
281         }
282         RetCode ret = DBufferManager::DImageBufferToDCameraBuffer(imageBuffer, buffer);
283         if (ret != RC_OK) {
284             DHLOGE("Convert image buffer to distributed camera buffer failed.");
285             return DCamRetCode::FAILED;
286         }
287     }
288 
289     {
290         std::lock_guard<std::mutex> lockSync(lockSync_);
291         captureBufferCount_++;
292     }
293     DHLOGD("Get buffer success. index = %{public}d, size = %{public}d", buffer.index_, buffer.size_);
294     return DCamRetCode::SUCCESS;
295 }
296 
FlushDCameraBuffer(const DCameraBuffer & buffer)297 DCamRetCode DCameraStream::FlushDCameraBuffer(const DCameraBuffer &buffer)
298 {
299     std::lock_guard<std::mutex> lockBuffer(bufferQueueMutex_);
300     shared_ptr<DImageBuffer> imageBuffer = nullptr;
301     for (auto iter = bufferConfigMap_.begin(); iter != bufferConfigMap_.end(); ++iter) {
302         if (buffer.index_ == iter->first->GetIndex()) {
303             imageBuffer = iter->first;
304             break;
305         }
306     }
307     if (imageBuffer == nullptr) {
308         DHLOGE("Cannot found image buffer, buffer index = %{public}d.", buffer.index_);
309         return DCamRetCode::INVALID_ARGUMENT;
310     }
311 
312     if (dcStreamBufferMgr_ != nullptr) {
313         RetCode ret = dcStreamBufferMgr_->RemoveBuffer(imageBuffer);
314         if (ret != RC_OK) {
315             DHLOGE("Buffer manager remove buffer failed: %{public}d", ret);
316         }
317     }
318 
319     auto bufCfg = bufferConfigMap_.find(imageBuffer);
320     if (bufCfg == bufferConfigMap_.end()) {
321         DHLOGE("Cannot get bufferConfig.");
322         return DCamRetCode::INVALID_ARGUMENT;
323     }
324     auto surfaceBuffer = std::get<0>(bufCfg->second);
325     int64_t timeStamp = static_cast<int64_t>(GetVideoTimeStamp());
326     OHOS::BufferFlushConfig flushConf = {
327         .damage = { .x = 0, .y = 0, .w = dcStreamInfo_->width_, .h = dcStreamInfo_->height_ },
328         .timestamp = timeStamp
329     };
330     if (dcStreamProducer_ != nullptr) {
331         SetSurfaceBuffer(surfaceBuffer, buffer);
332         OHOS::sptr<OHOS::SyncFence> autoFence(new(std::nothrow) OHOS::SyncFence(-1));
333         int ret = dcStreamProducer_->FlushBuffer(surfaceBuffer, autoFence, flushConf);
334         if (ret != 0) {
335             DHLOGI("FlushBuffer error: %{public}d", ret);
336         }
337     }
338     bufferConfigMap_.erase(bufCfg);
339     return DCamRetCode::SUCCESS;
340 }
341 
ReturnDCameraBuffer(const DCameraBuffer & buffer)342 DCamRetCode DCameraStream::ReturnDCameraBuffer(const DCameraBuffer &buffer)
343 {
344     DCamRetCode ret = FlushDCameraBuffer(buffer);
345     if (ret != DCamRetCode::SUCCESS) {
346         DHLOGE("Flush Buffer failed, ret: %{public}d", ret);
347         return ret;
348     }
349 
350     {
351         std::lock_guard<std::mutex> lockSync(lockSync_);
352         captureBufferCount_--;
353     }
354     cv_.notify_one();
355     return DCamRetCode::SUCCESS;
356 }
357 
SetSurfaceBuffer(OHOS::sptr<OHOS::SurfaceBuffer> & surfaceBuffer,const DCameraBuffer & buffer)358 void DCameraStream::SetSurfaceBuffer(OHOS::sptr<OHOS::SurfaceBuffer>& surfaceBuffer, const DCameraBuffer &buffer)
359 {
360     if (dcStreamInfo_->intent_ == StreamIntent::VIDEO) {
361         int32_t size = (dcStreamInfo_->width_) * (dcStreamInfo_->height_) * YUV_WIDTH_RATIO / YUV_HEIGHT_RATIO;
362         int64_t timeStamp = static_cast<int64_t>(GetVideoTimeStamp());
363         surfaceBuffer->GetExtraData()->ExtraSet("dataSize", size);
364         surfaceBuffer->GetExtraData()->ExtraSet("isKeyFrame", (int32_t)0);
365         surfaceBuffer->GetExtraData()->ExtraSet("timeStamp", timeStamp);
366     } else if (dcStreamInfo_->intent_ == StreamIntent::STILL_CAPTURE) {
367         int32_t size = buffer.size_;
368         int64_t timeStamp = static_cast<int64_t>(GetCurrentLocalTimeStamp());
369         surfaceBuffer->GetExtraData()->ExtraSet("dataSize", size);
370         surfaceBuffer->GetExtraData()->ExtraSet("isKeyFrame", (int32_t)0);
371         surfaceBuffer->GetExtraData()->ExtraSet("timeStamp", timeStamp);
372     }
373 }
374 
GetVideoTimeStamp()375 uint64_t DCameraStream::GetVideoTimeStamp()
376 {
377     struct timespec tp;
378     clock_gettime(CLOCK_MONOTONIC, &tp);
379     return tp.tv_sec * SEC_TO_NSEC_TIMES + tp.tv_nsec;
380 }
381 
DoCapture()382 void DCameraStream::DoCapture()
383 {
384     DHLOGI("Do capture, streamId %{public}d", dcStreamInfo_->streamId_);
385     std::lock_guard<std::mutex> lockRequest(requestMutex_);
386     isCancelCapture_ = false;
387 }
388 
CancelCaptureWait()389 void DCameraStream::CancelCaptureWait()
390 {
391     DHLOGI("Cancel capture wait for, streamId %{public}d", dcStreamInfo_->streamId_);
392     std::lock_guard<std::mutex> lockRequest(requestMutex_);
393     if (isCancelCapture_) {
394         DHLOGI("CacelCapture has already execute");
395         return;
396     }
397     if (captureBufferCount_ != 0) {
398         DHLOGI("StreamId:%{public}d has request that not return and wait, captureBufferCount=%{public}d",
399             dcStreamInfo_->streamId_, captureBufferCount_);
400     }
401     {
402         std::unique_lock<std::mutex> lockSync(lockSync_);
403         cv_.wait(lockSync, [this] { return !captureBufferCount_; });
404     }
405     isCancelCapture_ = true;
406     DHLOGI("Cancel capture wait for success, streamId %{public}d", dcStreamInfo_->streamId_);
407     return;
408 }
409 
CancelDCameraBuffer()410 DCamRetCode DCameraStream::CancelDCameraBuffer()
411 {
412     DHLOGI("Cancel dcamera buffer wait for, streamId %{public}d", dcStreamInfo_->streamId_);
413     std::lock_guard<std::mutex> lockRequest(requestMutex_);
414     if (dcStreamBufferMgr_ == nullptr || dcStreamProducer_ == nullptr || isCancelBuffer_) {
415         DHLOGE("BufferManager or Producer is null or isCanceled is true.");
416         return DCamRetCode::SUCCESS;
417     }
418 
419     if (captureBufferCount_ != 0) {
420         DHLOGI("StreamId:%{public}d has request that not return, captureBufferCount=%{public}d",
421             dcStreamInfo_->streamId_, captureBufferCount_);
422     }
423     {
424         std::unique_lock<std::mutex> lockSync(lockSync_);
425         cv_.wait(lockSync, [this] { return !captureBufferCount_; });
426     }
427 
428     {
429         std::lock_guard<std::mutex> lockBuffer(bufferQueueMutex_);
430         while (true) {
431             std::shared_ptr<DImageBuffer> imageBuffer = dcStreamBufferMgr_->AcquireBuffer();
432             if (imageBuffer != nullptr) {
433                 auto bufCfg = bufferConfigMap_.find(imageBuffer);
434                 if (bufCfg == bufferConfigMap_.end()) {
435                     DHLOGE("Buffer not in map.");
436                     return DCamRetCode::INVALID_ARGUMENT;
437                 }
438                 auto surfaceBuffer = std::get<0>(bufCfg->second);
439                 if (dcStreamProducer_ != nullptr) {
440                     dcStreamProducer_->CancelBuffer(surfaceBuffer);
441                 }
442                 bufferConfigMap_.erase(bufCfg);
443             } else {
444                 break;
445             }
446         }
447         index_ = -1;
448     }
449     captureBufferCount_ = 0;
450     isCancelBuffer_ = true;
451     DHLOGI("Cancel dcamera buffer wait for success, streamId %{public}d", dcStreamInfo_->streamId_);
452     return DCamRetCode::SUCCESS;
453 }
454 
HasBufferQueue()455 bool DCameraStream::HasBufferQueue()
456 {
457     if (dcStreamProducer_ == nullptr || !isBufferMgrInited_) {
458         return false;
459     }
460     return true;
461 }
462 } // namespace DistributedHardware
463 } // namespace OHOS
464