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