• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "stream_base.h"
17 #include "buffer_adapter.h"
18 #include "buffer_manager.h"
19 #include "watchdog.h"
20 
21 namespace OHOS::Camera {
22 std::map<VdiStreamIntent, std::string> IStream::g_availableStreamType = {
23     {PREVIEW, STREAM_INTENT_TO_STRING(PREVIEW)},
24     {VIDEO, STREAM_INTENT_TO_STRING(VIDEO)},
25     {STILL_CAPTURE, STREAM_INTENT_TO_STRING(STILL_CAPTURE)},
26     {POST_VIEW, STREAM_INTENT_TO_STRING(POST_VIEW)},
27     {ANALYZE, STREAM_INTENT_TO_STRING(ANALYZE)},
28     {CUSTOM, STREAM_INTENT_TO_STRING(CUSTOM)},
29 };
30 
StreamBase(const int32_t id,const VdiStreamIntent type,std::shared_ptr<IPipelineCore> & p,std::shared_ptr<CaptureMessageOperator> & m)31 StreamBase::StreamBase(const int32_t id,
32                        const VdiStreamIntent type,
33                        std::shared_ptr<IPipelineCore>& p,
34                        std::shared_ptr<CaptureMessageOperator>& m)
35 {
36     streamId_ = id;
37     streamType_ = static_cast<int32_t>(type);
38     pipelineCore_ = p;
39     messenger_ = m;
40 }
41 
~StreamBase()42 StreamBase::~StreamBase()
43 {
44     if (state_ == STREAM_STATE_BUSY) {
45         StopStream();
46     }
47 
48     if (hostStreamMgr_ != nullptr) {
49         hostStreamMgr_->DestroyHostStream({streamId_});
50     }
51 
52     if (pipeline_ != nullptr) {
53         pipeline_->DestroyPipeline({streamId_});
54     }
55 }
56 
ConfigStream(StreamConfiguration & config)57 RetCode StreamBase::ConfigStream(StreamConfiguration& config)
58 {
59     std::unique_lock<std::mutex> l(smLock_);
60     if (state_ != STREAM_STATE_IDLE) {
61         return RC_ERROR;
62     }
63 
64     streamConfig_ = config;
65     streamConfig_.usage = GetUsage();
66     if (tunnel_ != nullptr) {
67         streamConfig_.tunnelMode = true;
68     }
69     streamConfig_.bufferCount = GetBufferCount();
70     streamConfig_.maxBatchCaptureCount = 1;
71     streamConfig_.maxCaptureCount = 1;
72     // get device cappability to override configuration
73     return RC_OK;
74 }
75 
CommitStream()76 RetCode StreamBase::CommitStream()
77 {
78     std::unique_lock<std::mutex> l(smLock_);
79     if (state_ != STREAM_STATE_IDLE) {
80         return RC_ERROR;
81     }
82 
83     CHECK_IF_PTR_NULL_RETURN_VALUE(pipelineCore_, RC_ERROR);
84 
85     pipeline_ = pipelineCore_->GetStreamPipelineCore();
86     CHECK_IF_PTR_NULL_RETURN_VALUE(pipeline_, RC_ERROR);
87 
88     hostStreamMgr_ = pipelineCore_->GetHostStreamMgr();
89     CHECK_IF_PTR_NULL_RETURN_VALUE(hostStreamMgr_, RC_ERROR);
90 
91     HostStreamInfo info;
92     info.type_ = static_cast<VdiStreamIntent>(streamType_);
93     info.streamId_ = streamId_;
94     info.width_ = streamConfig_.width;
95     info.height_ = streamConfig_.height;
96     info.format_ = streamConfig_.format;
97     info.usage_ = streamConfig_.usage;
98     info.encodeType_ = streamConfig_.encodeType;
99 
100     if (streamConfig_.tunnelMode) {
101         BufferManager* mgr = BufferManager::GetInstance();
102         CHECK_IF_PTR_NULL_RETURN_VALUE(mgr, RC_ERROR);
103 
104         if (bufferPool_ == nullptr) {
105             poolId_ = mgr->GenerateBufferPoolId();
106             CHECK_IF_EQUAL_RETURN_VALUE(poolId_, 0, RC_ERROR);
107             bufferPool_ = mgr->GetBufferPool(poolId_);
108             if (bufferPool_ == nullptr) {
109                 CAMERA_LOGE("stream [id:%{public}d] get buffer pool failed.", streamId_);
110                 return RC_ERROR;
111             }
112         }
113 
114         info.bufferPoolId_ = poolId_;
115         info.bufferCount_ = GetBufferCount();
116         RetCode rc = bufferPool_->Init(streamConfig_.width, streamConfig_.height, streamConfig_.usage,
117                                        streamConfig_.format, GetBufferCount(), CAMERA_BUFFER_SOURCE_TYPE_EXTERNAL);
118         if (rc != RC_OK) {
119             CAMERA_LOGE("stream [id:%{public}d] initialize buffer pool failed.", streamId_);
120             return RC_ERROR;
121         }
122     }
123 
124     RetCode rc = hostStreamMgr_->CreateHostStream(info, [this](std::shared_ptr<IBuffer> buffer) {
125         HandleResult(buffer);
126         return;
127     });
128     if (rc != RC_OK) {
129         CAMERA_LOGE("commit stream [id:%{public}d] to pipeline failed.", streamId_);
130         return RC_ERROR;
131     }
132     CAMERA_LOGI("commit a stream to pipeline id[%{public}d], w[%{public}d], h[%{public}d], poolId[%{public}llu], \
133         encodeType = %{public}d", info.streamId_, info.width_, info.height_, info.bufferPoolId_, info.encodeType_);
134     state_ = STREAM_STATE_ACTIVE;
135 
136     return RC_OK;
137 }
138 
StartStream()139 RetCode StreamBase::StartStream()
140 {
141     CHECK_IF_PTR_NULL_RETURN_VALUE(pipeline_, RC_ERROR);
142 
143     std::unique_lock<std::mutex> l(smLock_);
144     if (state_ != STREAM_STATE_ACTIVE) {
145         return RC_ERROR;
146     }
147 
148     CAMERA_LOGI("start stream [id:%{public}d] begin", streamId_);
149     tunnel_->NotifyStart();
150 
151     RetCode rc = pipeline_->Prepare({streamId_});
152     if (rc != RC_OK) {
153         CAMERA_LOGE("pipeline [id:%{public}d] prepare failed", streamId_);
154         return rc;
155     }
156 
157     state_ = STREAM_STATE_BUSY;
158     std::string threadName =
159         g_availableStreamType[static_cast<VdiStreamIntent>(streamType_)] + "#" + std::to_string(streamId_);
160     handler_ = std::make_unique<std::thread>([this, &threadName] {
161         prctl(PR_SET_NAME, threadName.c_str());
162         while (state_ == STREAM_STATE_BUSY) {
163             tunnel_->DumpStats(3); // set output interval to 30 second
164             HandleRequest();
165         }
166     });
167     if (handler_ == nullptr) {
168         state_ = STREAM_STATE_ACTIVE;
169         return RC_ERROR;
170     }
171 
172     rc = pipeline_->Start({streamId_});
173     if (rc != RC_OK) {
174         CAMERA_LOGE("pipeline [%{public}d] start failed", streamId_);
175         return RC_ERROR;
176     }
177     CAMERA_LOGI("start stream [id:%{public}d] end", streamId_);
178 
179     return RC_OK;
180 }
181 
StopStream()182 RetCode StreamBase::StopStream()
183 {
184     CHECK_IF_PTR_NULL_RETURN_VALUE(pipeline_, RC_ERROR);
185     std::unique_lock<std::mutex> l(smLock_);
186     if (state_ == STREAM_STATE_IDLE) {
187         CAMERA_LOGI("stream [id:%{public}d], no need to stop", streamId_);
188         return RC_OK;
189     }
190     CAMERA_LOGI("stop stream [id:%{public}d] begin", streamId_);
191 
192     state_ = STREAM_STATE_IDLE;
193 
194     tunnel_->NotifyStop();
195     cv_.notify_one();
196     if (handler_ != nullptr) {
197         handler_->join();
198         handler_ = nullptr;
199     }
200 
201     if (!waitingList_.empty()) {
202         auto request = waitingList_.front();
203         if (request != nullptr && request->IsContinous()) {
204             request->Cancel();
205         }
206     }
207     {
208         std::unique_lock<std::mutex> l(wtLock_);
209         waitingList_.clear();
210     }
211 
212     RetCode rc = pipeline_->Flush({streamId_});
213     if (rc != RC_OK) {
214         CAMERA_LOGE("stream [id:%{public}d], pipeline flush failed", streamId_);
215         return RC_ERROR;
216     }
217 
218     CAMERA_LOGI("stream [id:%{public}d] is waiting buffers returned", streamId_);
219     tunnel_->WaitForAllBufferReturned();
220     CAMERA_LOGI("stream [id:%{public}d], all buffers are returned.", streamId_);
221 
222     rc = pipeline_->Stop({streamId_});
223     if (rc != RC_OK) {
224         CAMERA_LOGE("stream [id:%{public}d], pipeline stop failed", streamId_);
225         return RC_ERROR;
226     }
227 
228     if (lastRequest_ != nullptr && lastRequest_->IsContinous() && !inTransitList_.empty() && messenger_ != nullptr) {
229         std::shared_ptr<ICaptureMessage> endMessage =
230             std::make_shared<CaptureEndedMessage>(streamId_, lastRequest_->GetCaptureId(),
231             lastRequest_->GetEndTime(), lastRequest_->GetOwnerCount(), tunnel_->GetFrameCount());
232         CAMERA_LOGV("end of stream [%{public}d], ready to send end message", streamId_);
233         messenger_->SendMessage(endMessage);
234     }
235 
236     CAMERA_LOGI("stop stream [id:%{public}d] end", streamId_);
237     isFirstRequest = true;
238     inTransitList_.clear();
239     tunnel_->CleanBuffers();
240     bufferPool_->ClearBuffers();
241     return RC_OK;
242 }
243 
AddRequest(std::shared_ptr<CaptureRequest> & request)244 RetCode StreamBase::AddRequest(std::shared_ptr<CaptureRequest>& request)
245 {
246     CHECK_IF_PTR_NULL_RETURN_VALUE(request, RC_ERROR);
247     request->AddOwner(shared_from_this());
248 
249     request->SetFirstRequest(false);
250     if (isFirstRequest) {
251         RetCode rc = StartStream();
252         if (rc != RC_OK) {
253             CAMERA_LOGE("start stream [id:%{public}d] failed", streamId_);
254             return RC_ERROR;
255         }
256         request->SetFirstRequest(true);
257         isFirstRequest = false;
258     }
259 
260     {
261         std::unique_lock<std::mutex> l(wtLock_);
262         waitingList_.emplace_back(request);
263         cv_.notify_one();
264     }
265 
266     return RC_OK;
267 }
268 
CancelRequest(const std::shared_ptr<CaptureRequest> & request)269 RetCode StreamBase::CancelRequest(const std::shared_ptr<CaptureRequest>& request)
270 {
271     CHECK_IF_PTR_NULL_RETURN_VALUE(request, RC_ERROR);
272     CHECK_IF_PTR_NULL_RETURN_VALUE(messenger_, RC_ERROR);
273     {
274         // We don't care if this request is continious-capture or single-capture, just erase it.
275         // And those requests in inTransitList_ removed in HandleResult.
276         std::unique_lock<std::mutex> wl(wtLock_);
277         auto it = std::find(waitingList_.begin(), waitingList_.end(), request);
278         if (it != waitingList_.end()) {
279             waitingList_.erase(it);
280             CAMERA_LOGI("stream [id:%{public}d], cancel request(capture id:%{public}d) success",
281                 streamId_, request->GetCaptureId());
282         }
283     }
284 
285     if (request->IsContinous()) {
286         // may be this is the last request
287         std::unique_lock<std::mutex> tl(tsLock_);
288         auto it = std::find(inTransitList_.begin(), inTransitList_.end(), request);
289         if (it == inTransitList_.end()) {
290             std::shared_ptr<ICaptureMessage> endMessage =
291                 std::make_shared<CaptureEndedMessage>(streamId_, request->GetCaptureId(), request->GetEndTime(),
292                                                       request->GetOwnerCount(), tunnel_->GetFrameCount());
293             CAMERA_LOGV("end of stream [%{public}d], ready to send end message", streamId_);
294             messenger_->SendMessage(endMessage);
295             pipeline_->CancelCapture({streamId_});
296         }
297     }
298     return RC_OK;
299 }
300 
HandleRequest()301 void StreamBase::HandleRequest()
302 {
303     if (waitingList_.empty()) {
304         std::unique_lock<std::mutex> l(wtLock_);
305         if (waitingList_.empty()) {
306             cv_.wait(l, [this] { return !(state_ == STREAM_STATE_BUSY && waitingList_.empty()); });
307         }
308     }
309     if (state_ != STREAM_STATE_BUSY) {
310         return;
311     }
312 
313     std::shared_ptr<CaptureRequest> request = nullptr;
314     {
315         // keep a copy of continious-capture in waitingList_, unless it's going to be canceled.
316         std::unique_lock<std::mutex> l(wtLock_);
317         if (waitingList_.empty()) {
318             return;
319         }
320         request = waitingList_.front();
321         CHECK_IF_PTR_NULL_RETURN_VOID(request);
322         CAMERA_LOGI("HandleRequest streamId = [%{public}d] and needCancel = [%{public}d]",
323             streamId_, request->NeedCancel() ? 1 : 0);
324         if (!request->IsContinous()) {
325             waitingList_.pop_front();
326         }
327     }
328     if (request == nullptr) {
329         CAMERA_LOGE("fatal error, stream [%{public}d] request list is not empty, but can't get one", streamId_);
330         return;
331     }
332 
333     if (request->NeedCancel()) {
334         return;
335     }
336 
337     request->Process(streamId_);
338 
339     return;
340 }
341 
Capture(const std::shared_ptr<CaptureRequest> & request)342 RetCode StreamBase::Capture(const std::shared_ptr<CaptureRequest>& request)
343 {
344     CHECK_IF_PTR_NULL_RETURN_VALUE(request, RC_ERROR);
345     CHECK_IF_PTR_NULL_RETURN_VALUE(pipeline_, RC_ERROR);
346 
347     RetCode rc = RC_ERROR;
348     if (request->IsFirstOne() && !request->IsContinous()) {
349         uint32_t n = GetBufferCount();
350         for (uint32_t i = 0; i < n; i++) {
351             DeliverBuffer();
352         }
353     } else {
354         do {
355             rc = DeliverBuffer();
356         } while (rc != RC_OK && state_ == STREAM_STATE_BUSY);
357     }
358 
359     rc = pipeline_->Config({streamId_}, request->GetCaptureSetting());
360     if (rc != RC_OK) {
361         CAMERA_LOGE("stream [id:%{public}d] config pipeline failed.", streamId_);
362         return RC_ERROR;
363     }
364 
365     rc = pipeline_->Capture({streamId_}, request->GetCaptureId());
366     if (rc != RC_OK) {
367         CAMERA_LOGE("stream [id:%{public}d] take a capture failed.", streamId_);
368         return RC_ERROR;
369     }
370 
371     {
372         std::unique_lock<std::mutex> l(tsLock_);
373         inTransitList_.emplace_back(request);
374     }
375 
376     if (request->IsFirstOne()) {
377         if (messenger_ == nullptr) {
378             CAMERA_LOGE("stream [id:%{public}d] can't send message, messenger_ is null", streamId_);
379             return RC_ERROR;
380         }
381         std::shared_ptr<ICaptureMessage> startMessage = std::make_shared<CaptureStartedMessage>(
382             streamId_, request->GetCaptureId(), request->GetBeginTime(), request->GetOwnerCount());
383         messenger_->SendMessage(startMessage);
384         request->SetFirstRequest(false);
385     }
386 
387     return RC_OK;
388 }
389 
DeliverBuffer()390 RetCode StreamBase::DeliverBuffer()
391 {
392     CHECK_IF_PTR_NULL_RETURN_VALUE(tunnel_, RC_ERROR);
393     CHECK_IF_PTR_NULL_RETURN_VALUE(bufferPool_, RC_ERROR);
394 
395     std::shared_ptr<IBuffer> buffer = tunnel_->GetBuffer();
396     CHECK_IF_PTR_NULL_RETURN_VALUE(buffer, RC_ERROR);
397 
398     buffer->SetEncodeType(streamConfig_.encodeType);
399     buffer->SetStreamId(streamId_);
400     bufferPool_->AddBuffer(buffer);
401     CAMERA_LOGI("stream [id:%{public}d] enqueue buffer index:%{public}d", streamId_, buffer->GetIndex());
402     return RC_OK;
403 }
404 
HandleResult(std::shared_ptr<IBuffer> & buffer)405 void StreamBase::HandleResult(std::shared_ptr<IBuffer>& buffer)
406 {
407     CHECK_IF_PTR_NULL_RETURN_VOID(buffer);
408     if (buffer->GetBufferStatus() == CAMERA_BUFFER_STATUS_INVALID) {
409         CAMERA_LOGI("stream [id:%{public}d], this buffer(index:%{public}d) has nothing to do with request.", streamId_,
410                     buffer->GetIndex());
411         ReceiveBuffer(buffer);
412         return;
413     }
414 
415     if (buffer->GetStreamId() != streamId_) {
416         CAMERA_LOGE("fatal error, stream [%{public}d] reveived a wrong buffer, index:%{public}d. \
417             this buffer belongs to stream:%{public}d", streamId_, buffer->GetIndex(), buffer->GetStreamId());
418         return;
419     }
420 
421     int32_t captureId = buffer->GetCaptureId();
422     std::shared_ptr<CaptureRequest> request = nullptr;
423     {
424         std::unique_lock<std::mutex> l(tsLock_);
425         for (auto& r : inTransitList_) {
426             if (r == nullptr) {
427                 continue;
428             }
429             if (r->GetCaptureId() == captureId) {
430                 request = r;
431                 break;
432             }
433         }
434     }
435     if (request == nullptr) {
436         CAMERA_LOGI("stream [id:%{public}d], this buffer(index:%{public}d) has nothing to do with request.",
437             streamId_, buffer->GetIndex());
438         buffer->SetBufferStatus(CAMERA_BUFFER_STATUS_INVALID);
439         ReceiveBuffer(buffer);
440         return;
441     }
442     request->AttachBuffer(buffer);
443     // To synchronize multiple stream, bottom-layer device stream need be synchronized first.
444     request->OnResult(streamId_);
445     lastRequest_ = request;
446 }
447 
OnFrame(const std::shared_ptr<CaptureRequest> & request)448 RetCode StreamBase::OnFrame(const std::shared_ptr<CaptureRequest>& request)
449 {
450     CHECK_IF_PTR_NULL_RETURN_VALUE(request, RC_ERROR);
451     CHECK_IF_PTR_NULL_RETURN_VALUE(pipeline_, RC_ERROR);
452     CHECK_IF_PTR_NULL_RETURN_VALUE(messenger_, RC_ERROR);
453     auto buffer = request->GetAttachedBuffer();
454     CameraBufferStatus status = buffer->GetBufferStatus();
455     if (status != CAMERA_BUFFER_STATUS_OK) {
456         if (status != CAMERA_BUFFER_STATUS_DROP) {
457             std::shared_ptr<ICaptureMessage> errorMessage =
458                 std::make_shared<CaptureErrorMessage>(streamId_, request->GetCaptureId(), request->GetEndTime(),
459                                                       request->GetOwnerCount(), static_cast<VdiStreamError>(status));
460             messenger_->SendMessage(errorMessage);
461         } else {
462             CAMERA_LOGE("stream [id:%{public}d] drop buffer index:%{public}d, status:%{public}d",
463                 streamId_, buffer->GetIndex(), buffer->GetBufferStatus());
464             ReceiveBuffer(buffer);
465             return RC_OK;
466         }
467     }
468     if (request->NeedShutterCallback()) {
469         std::shared_ptr<ICaptureMessage> shutterMessage = std::make_shared<FrameShutterMessage>(
470             streamId_, request->GetCaptureId(), request->GetEndTime(), request->GetOwnerCount());
471         messenger_->SendMessage(shutterMessage);
472     }
473 
474     bool isEnded = false;
475     if (!request->IsContinous()) {
476         isEnded = true;
477     } else if (request->NeedCancel()) {
478         isEnded = true;
479     }
480 
481     {
482         // inTransitList_ may has multiple copies of continious-capture request, we just need erase one of them.
483         std::unique_lock<std::mutex> l(tsLock_);
484         for (auto it = inTransitList_.begin(); it != inTransitList_.end(); it++) {
485             if ((*it) == request) {
486                 inTransitList_.erase(it);
487                 break;
488             }
489         }
490 
491         if (isEnded) {
492             // if this is the last request of capture, send CaptureEndedMessage.
493             auto it = std::find(inTransitList_.begin(), inTransitList_.end(), request);
494             if (it == inTransitList_.end()) {
495                 std::shared_ptr<ICaptureMessage> endMessage =
496                     std::make_shared<CaptureEndedMessage>(streamId_, request->GetCaptureId(), request->GetEndTime(),
497                                                           request->GetOwnerCount(), tunnel_->GetFrameCount());
498                 CAMERA_LOGV("end of stream [%d], ready to send end message, capture id = %d",
499                     streamId_, request->GetCaptureId());
500                 messenger_->SendMessage(endMessage);
501                 pipeline_->CancelCapture({streamId_});
502             }
503         }
504     }
505     CAMERA_LOGI("stream = [%{public}d] OnFrame and NeedCancel = [%{public}d]",
506         buffer->GetStreamId(), request->NeedCancel() ? 1 : 0);
507     if (request->NeedCancel()) {
508         buffer->SetBufferStatus(CAMERA_BUFFER_STATUS_DROP);
509     } else {
510         buffer->SetBufferStatus(CAMERA_BUFFER_STATUS_OK);
511     }
512     ReceiveBuffer(buffer);
513     return RC_OK;
514 }
515 
ReceiveBuffer(std::shared_ptr<IBuffer> & buffer)516 RetCode StreamBase::ReceiveBuffer(std::shared_ptr<IBuffer>& buffer)
517 {
518     CHECK_IF_PTR_NULL_RETURN_VALUE(buffer, RC_ERROR);
519     CHECK_IF_PTR_NULL_RETURN_VALUE(tunnel_, RC_ERROR);
520     CHECK_IF_PTR_NULL_RETURN_VALUE(bufferPool_, RC_ERROR);
521 
522     CAMERA_LOGI("stream [id:%{public}d] dequeue buffer index:%{public}d, status:%{public}d",
523         streamId_, buffer->GetIndex(), buffer->GetBufferStatus());
524     bufferPool_->ReturnBuffer(buffer);
525     tunnel_->PutBuffer(buffer);
526     return RC_OK;
527 }
528 
GetFrameCount() const529 uint64_t StreamBase::GetFrameCount() const
530 {
531     CHECK_IF_PTR_NULL_RETURN_VALUE(tunnel_, 0);
532     return tunnel_->GetFrameCount();
533 }
534 
AttachStreamTunnel(std::shared_ptr<StreamTunnel> & tunnel)535 RetCode StreamBase::AttachStreamTunnel(std::shared_ptr<StreamTunnel>& tunnel)
536 {
537     std::unique_lock<std::mutex> l(smLock_);
538     if (state_ == STREAM_STATE_BUSY || state_ == STREAM_STATE_OFFLINE) {
539         return RC_ERROR;
540     }
541 
542     tunnel_ = tunnel;
543     CHECK_IF_PTR_NULL_RETURN_VALUE(tunnel_, RC_ERROR);
544     tunnel_->SetBufferCount(GetBufferCount());
545     TunnelConfig config = {(uint32_t)streamConfig_.width, (uint32_t)streamConfig_.height,
546         (uint32_t)streamConfig_.format, streamConfig_.usage};
547     tunnel_->Config(config);
548     tunnel_->SetStreamId(streamId_);
549     streamConfig_.tunnelMode = true;
550     return RC_OK;
551 }
552 
DetachStreamTunnel()553 RetCode StreamBase::DetachStreamTunnel()
554 {
555     std::unique_lock<std::mutex> l(smLock_);
556     if (state_ == STREAM_STATE_BUSY || state_ == STREAM_STATE_OFFLINE) {
557         return RC_ERROR;
558     }
559 
560     tunnel_.reset();
561     streamConfig_.tunnelMode = false;
562 
563     state_ = STREAM_STATE_IDLE;
564     return RC_OK;
565 }
566 
ChangeToOfflineStream(std::shared_ptr<OfflineStream> offlineStream)567 RetCode StreamBase::ChangeToOfflineStream(std::shared_ptr<OfflineStream> offlineStream)
568 {
569     (void)offlineStream;
570     return RC_OK;
571 }
572 
GetUsage()573 uint64_t StreamBase::GetUsage()
574 {
575     return CAMERA_USAGE_SW_WRITE_OFTEN | CAMERA_USAGE_SW_READ_OFTEN | CAMERA_USAGE_MEM_DMA;
576 }
577 
GetBufferCount()578 uint32_t StreamBase::GetBufferCount()
579 {
580     return 3; // 3: buffer count
581 }
582 
GetStreamAttribute() const583 StreamConfiguration StreamBase::GetStreamAttribute() const
584 {
585     return streamConfig_;
586 }
587 
GetStreamId() const588 int32_t StreamBase::GetStreamId() const
589 {
590     return streamId_;
591 }
592 
IsRunning() const593 bool StreamBase::IsRunning() const
594 {
595     return state_ == STREAM_STATE_BUSY;
596 }
597 
GetTunnelMode() const598 bool StreamBase::GetTunnelMode() const
599 {
600     return streamConfig_.tunnelMode;
601 }
602 
DumpStatsInfo() const603 void StreamBase::DumpStatsInfo() const
604 {
605     if (tunnel_ != nullptr) {
606         tunnel_->DumpStats();
607     }
608 }
609 
ReleaseStreamBufferPool()610 void StreamBase::ReleaseStreamBufferPool()
611 {
612     BufferManager* mgr = BufferManager::GetInstance();
613     if (mgr != nullptr) {
614         mgr->EraseBufferPoolMapById(poolId_);
615     }
616     bufferPool_ = nullptr;
617 }
618 } // namespace OHOS::Camera
619