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         config.width = JPEG_MAX_SIZE;
202         config.height = 1;
203         config.format = GraphicPixelFormat::GRAPHIC_PIXEL_FMT_BLOB;
204     }
205     CHECK_AND_RETURN_RET_LOG(
206         dcStreamProducer_ == nullptr, DCamRetCode::INVALID_ARGUMENT, "dcStreamProducer_ is nullptr");
207     OHOS::SurfaceError surfaceError = dcStreamProducer_->RequestBuffer(surfaceBuffer, syncFence, config);
208     if (surfaceError == OHOS::SURFACE_ERROR_NO_BUFFER) {
209         DHLOGE("No available buffer to request in surface.");
210         return DCamRetCode::EXCEED_MAX_NUMBER;
211     }
212 
213     if (surfaceError != OHOS::SURFACE_ERROR_OK || surfaceBuffer == nullptr) {
214         DHLOGE("Get producer buffer failed. [streamId = %{public}d] [sfError = %{public}d]",
215             dcStreamInfo_->streamId_, surfaceError);
216         return DCamRetCode::EXCEED_MAX_NUMBER;
217     }
218     return SurfaceBufferToDImageBuffer(surfaceBuffer, syncFence);
219 }
220 
SurfaceBufferToDImageBuffer(OHOS::sptr<OHOS::SurfaceBuffer> &surfaceBuffer, OHOS::sptr<OHOS::SyncFence> &syncFence)221 DCamRetCode DCameraStream::SurfaceBufferToDImageBuffer(OHOS::sptr<OHOS::SurfaceBuffer> &surfaceBuffer,
222     OHOS::sptr<OHOS::SyncFence> &syncFence)
223 {
224     std::shared_ptr<DImageBuffer> imageBuffer = std::make_shared<DImageBuffer>();
225     RetCode ret = DBufferManager::SurfaceBufferToDImageBuffer(surfaceBuffer, imageBuffer);
226     if (ret != RC_OK) {
227         DHLOGE("Convert surfacebuffer to image buffer failed, streamId = %{public}d.", dcStreamInfo_->streamId_);
228         dcStreamProducer_->CancelBuffer(surfaceBuffer);
229         return DCamRetCode::EXCEED_MAX_NUMBER;
230     }
231 
232     imageBuffer->SetIndex(++index_);
233     imageBuffer->SetSyncFence(syncFence);
234     CHECK_AND_RETURN_RET_LOG(
235         dcStreamBufferMgr_ == nullptr, DCamRetCode::INVALID_ARGUMENT, "dcStreamBufferMgr_ is nullptr");
236     ret = dcStreamBufferMgr_->AddBuffer(imageBuffer);
237     if (ret != RC_OK) {
238         DHLOGE("Add buffer to buffer manager failed. [streamId = %{public}d]", dcStreamInfo_->streamId_);
239         dcStreamProducer_->CancelBuffer(surfaceBuffer);
240         return DCamRetCode::EXCEED_MAX_NUMBER;
241     }
242     DHLOGD("Add new image buffer success: index = %{public}d, fenceFd = %{public}d", imageBuffer->GetIndex(),
243         syncFence->Get());
244     auto itr = bufferConfigMap_.find(imageBuffer);
245     if (itr == bufferConfigMap_.end()) {
246         int32_t usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
247         auto bufferCfg = std::make_tuple(surfaceBuffer, usage);
248         bufferConfigMap_.insert(std::make_pair(imageBuffer, bufferCfg));
249     }
250     return DCamRetCode::SUCCESS;
251 }
252 
GetDCameraBuffer(DCameraBuffer &buffer)253 DCamRetCode DCameraStream::GetDCameraBuffer(DCameraBuffer &buffer)
254 {
255     std::lock_guard<std::mutex> lockRequest(requestMutex_);
256     if (isCancelBuffer_ || isCancelCapture_) {
257         DHLOGE("Buffer has already canceled.");
258         return DCamRetCode::FAILED;
259     }
260     {
261         std::lock_guard<std::mutex> lockBuffer(bufferQueueMutex_);
262         DCamRetCode retCode = GetNextRequest();
263         if (retCode != DCamRetCode::SUCCESS && retCode != DCamRetCode::EXCEED_MAX_NUMBER) {
264             DHLOGE("Get next request failed.");
265             return retCode;
266         }
267 
268         if (dcStreamBufferMgr_ == nullptr) {
269             DHLOGE("dcStreamBufferMgr_ is nullptr");
270             return DCamRetCode::FAILED;
271         }
272         std::shared_ptr<DImageBuffer> imageBuffer = dcStreamBufferMgr_->AcquireBuffer();
273         if (imageBuffer == nullptr) {
274             DHLOGE("Cannot get idle buffer.");
275             return DCamRetCode::EXCEED_MAX_NUMBER;
276         }
277         auto syncFence = imageBuffer->GetSyncFence();
278         if (syncFence != nullptr) {
279             syncFence->Wait(BUFFER_SYNC_FENCE_TIMEOUT);
280         }
281         RetCode ret = DBufferManager::DImageBufferToDCameraBuffer(imageBuffer, buffer);
282         if (ret != RC_OK) {
283             DHLOGE("Convert image buffer to distributed camera buffer failed.");
284             return DCamRetCode::FAILED;
285         }
286     }
287 
288     {
289         std::lock_guard<std::mutex> lockSync(lockSync_);
290         captureBufferCount_++;
291     }
292     DHLOGD("Get buffer success. index = %{public}d, size = %{public}d", buffer.index_, buffer.size_);
293     return DCamRetCode::SUCCESS;
294 }
295 
FlushDCameraBuffer(const DCameraBuffer &buffer)296 DCamRetCode DCameraStream::FlushDCameraBuffer(const DCameraBuffer &buffer)
297 {
298     std::lock_guard<std::mutex> lockBuffer(bufferQueueMutex_);
299     shared_ptr<DImageBuffer> imageBuffer = nullptr;
300     for (auto iter = bufferConfigMap_.begin(); iter != bufferConfigMap_.end(); ++iter) {
301         if (buffer.index_ == iter->first->GetIndex()) {
302             imageBuffer = iter->first;
303             break;
304         }
305     }
306     if (imageBuffer == nullptr) {
307         DHLOGE("Cannot found image buffer, buffer index = %{public}d.", buffer.index_);
308         return DCamRetCode::INVALID_ARGUMENT;
309     }
310 
311     if (dcStreamBufferMgr_ != nullptr) {
312         RetCode ret = dcStreamBufferMgr_->RemoveBuffer(imageBuffer);
313         if (ret != RC_OK) {
314             DHLOGE("Buffer manager remove buffer failed: %{public}d", ret);
315         }
316     }
317 
318     auto bufCfg = bufferConfigMap_.find(imageBuffer);
319     if (bufCfg == bufferConfigMap_.end()) {
320         DHLOGE("Cannot get bufferConfig.");
321         return DCamRetCode::INVALID_ARGUMENT;
322     }
323     auto surfaceBuffer = std::get<0>(bufCfg->second);
324     int64_t timeStamp = static_cast<int64_t>(GetVideoTimeStamp());
325     OHOS::BufferFlushConfig flushConf = {
326         .damage = { .x = 0, .y = 0, .w = dcStreamInfo_->width_, .h = dcStreamInfo_->height_ },
327         .timestamp = timeStamp
328     };
329     if (dcStreamProducer_ != nullptr) {
330         SetSurfaceBuffer(surfaceBuffer, buffer);
331         OHOS::sptr<OHOS::SyncFence> autoFence(new(std::nothrow) OHOS::SyncFence(-1));
332         int ret = dcStreamProducer_->FlushBuffer(surfaceBuffer, autoFence, flushConf);
333         if (ret != 0) {
334             DHLOGI("FlushBuffer error: %{public}d", ret);
335         }
336     }
337     bufferConfigMap_.erase(bufCfg);
338     return DCamRetCode::SUCCESS;
339 }
340 
ReturnDCameraBuffer(const DCameraBuffer &buffer)341 DCamRetCode DCameraStream::ReturnDCameraBuffer(const DCameraBuffer &buffer)
342 {
343     DCamRetCode ret = FlushDCameraBuffer(buffer);
344     if (ret != DCamRetCode::SUCCESS) {
345         DHLOGE("Flush Buffer failed, ret: %{public}d", ret);
346         return ret;
347     }
348 
349     {
350         std::lock_guard<std::mutex> lockSync(lockSync_);
351         captureBufferCount_--;
352     }
353     cv_.notify_one();
354     return DCamRetCode::SUCCESS;
355 }
356 
SetSurfaceBuffer(OHOS::sptr<OHOS::SurfaceBuffer>& surfaceBuffer, const DCameraBuffer &buffer)357 void DCameraStream::SetSurfaceBuffer(OHOS::sptr<OHOS::SurfaceBuffer>& surfaceBuffer, const DCameraBuffer &buffer)
358 {
359     if (dcStreamInfo_->intent_ == StreamIntent::VIDEO) {
360         int32_t size = (dcStreamInfo_->width_) * (dcStreamInfo_->height_) * YUV_WIDTH_RATIO / YUV_HEIGHT_RATIO;
361         int64_t timeStamp = static_cast<int64_t>(GetVideoTimeStamp());
362         surfaceBuffer->GetExtraData()->ExtraSet("dataSize", size);
363         surfaceBuffer->GetExtraData()->ExtraSet("isKeyFrame", (int32_t)0);
364         surfaceBuffer->GetExtraData()->ExtraSet("timeStamp", timeStamp);
365     } else if (dcStreamInfo_->intent_ == StreamIntent::STILL_CAPTURE) {
366         int32_t size = buffer.size_;
367         int64_t timeStamp = static_cast<int64_t>(GetCurrentLocalTimeStamp());
368         surfaceBuffer->GetExtraData()->ExtraSet("dataSize", size);
369         surfaceBuffer->GetExtraData()->ExtraSet("isKeyFrame", (int32_t)0);
370         surfaceBuffer->GetExtraData()->ExtraSet("timeStamp", timeStamp);
371     }
372 }
373 
GetVideoTimeStamp()374 uint64_t DCameraStream::GetVideoTimeStamp()
375 {
376     struct timespec tp;
377     clock_gettime(CLOCK_MONOTONIC, &tp);
378     return tp.tv_sec * SEC_TO_NSEC_TIMES + tp.tv_nsec;
379 }
380 
DoCapture()381 void DCameraStream::DoCapture()
382 {
383     DHLOGI("Do capture, streamId %{public}d", dcStreamInfo_->streamId_);
384     std::lock_guard<std::mutex> lockRequest(requestMutex_);
385     isCancelCapture_ = false;
386 }
387 
CancelCaptureWait()388 void DCameraStream::CancelCaptureWait()
389 {
390     DHLOGI("Cancel capture wait for, streamId %{public}d", dcStreamInfo_->streamId_);
391     std::lock_guard<std::mutex> lockRequest(requestMutex_);
392     if (isCancelCapture_) {
393         DHLOGI("CacelCapture has already execute");
394         return;
395     }
396     if (captureBufferCount_ != 0) {
397         DHLOGI("StreamId:%{public}d has request that not return and wait, captureBufferCount=%{public}d",
398             dcStreamInfo_->streamId_, captureBufferCount_);
399     }
400     {
401         std::unique_lock<std::mutex> lockSync(lockSync_);
402         cv_.wait(lockSync, [this] { return !captureBufferCount_; });
403     }
404     isCancelCapture_ = true;
405     DHLOGI("Cancel capture wait for success, streamId %{public}d", dcStreamInfo_->streamId_);
406     return;
407 }
408 
CancelDCameraBuffer()409 DCamRetCode DCameraStream::CancelDCameraBuffer()
410 {
411     DHLOGI("Cancel dcamera buffer wait for, streamId %{public}d", dcStreamInfo_->streamId_);
412     std::lock_guard<std::mutex> lockRequest(requestMutex_);
413     if (dcStreamBufferMgr_ == nullptr || dcStreamProducer_ == nullptr || isCancelBuffer_) {
414         DHLOGE("BufferManager or Producer is null or isCanceled is true.");
415         return DCamRetCode::SUCCESS;
416     }
417 
418     if (captureBufferCount_ != 0) {
419         DHLOGI("StreamId:%{public}d has request that not return, captureBufferCount=%{public}d",
420             dcStreamInfo_->streamId_, captureBufferCount_);
421     }
422     {
423         std::unique_lock<std::mutex> lockSync(lockSync_);
424         cv_.wait(lockSync, [this] { return !captureBufferCount_; });
425     }
426 
427     {
428         std::lock_guard<std::mutex> lockBuffer(bufferQueueMutex_);
429         while (true) {
430             std::shared_ptr<DImageBuffer> imageBuffer = dcStreamBufferMgr_->AcquireBuffer();
431             if (imageBuffer != nullptr) {
432                 auto bufCfg = bufferConfigMap_.find(imageBuffer);
433                 if (bufCfg == bufferConfigMap_.end()) {
434                     DHLOGE("Buffer not in map.");
435                     return DCamRetCode::INVALID_ARGUMENT;
436                 }
437                 auto surfaceBuffer = std::get<0>(bufCfg->second);
438                 if (dcStreamProducer_ != nullptr) {
439                     dcStreamProducer_->CancelBuffer(surfaceBuffer);
440                 }
441                 bufferConfigMap_.erase(bufCfg);
442             } else {
443                 break;
444             }
445         }
446         index_ = -1;
447     }
448     captureBufferCount_ = 0;
449     isCancelBuffer_ = true;
450     DHLOGI("Cancel dcamera buffer wait for success, streamId %{public}d", dcStreamInfo_->streamId_);
451     return DCamRetCode::SUCCESS;
452 }
453 
HasBufferQueue()454 bool DCameraStream::HasBufferQueue()
455 {
456     if (dcStreamProducer_ == nullptr || !isBufferMgrInited_) {
457         return false;
458     }
459     return true;
460 }
461 } // namespace DistributedHardware
462 } // namespace OHOS
463