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