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